diff options
18 files changed, 564 insertions, 233 deletions
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 8bdea93b1f4..7f2ea6cbeaa 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -589,8 +589,9 @@ typedef struct Scene { #define R_EXR_TILE_FILE 0x0400 #define R_COMP_FREE 0x0800 #define R_NO_IMAGE_LOAD 0x1000 -#define R_NO_TEX 0x2000 +#define R_NO_TEX 0x2000 #define R_STAMP_INFO 0x4000 +#define R_FULL_SAMPLE 0x8000 /* r->stamp */ #define R_STAMP_TIME 0x0001 diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_defocus.c b/source/blender/nodes/intern/CMP_nodes/CMP_defocus.c index 53d01ab1d12..a7db8c2d53d 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_defocus.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_defocus.c @@ -376,8 +376,10 @@ static void defocus_blur(bNode *node, CompBuf *new, CompBuf *img, CompBuf *zbuf, // some sort of visual feedback would be nice, or at least this text in the renderwin header // but for now just print some info in the console every 8 scanlines. if (((y & 7)==0) || (y==(img->y-1))) { - printf("\rdefocus: Processing Line %d of %d ... ", y+1, img->y); - fflush(stdout); + if(G.background==0) { + printf("\rdefocus: Processing Line %d of %d ... ", y+1, img->y); + fflush(stdout); + } } // esc set by main calling process if(node->exec & NODE_BREAK) diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_idMask.c b/source/blender/nodes/intern/CMP_nodes/CMP_idMask.c index abb9fa98d97..a40579ac3b2 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_idMask.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_idMask.c @@ -63,8 +63,25 @@ static void do_idmask(CompBuf *stackbuf, CompBuf *cbuf, float idnr) MEM_freeN(abuf); } +/* full sample version */ +static void do_idmask_fsa(CompBuf *stackbuf, CompBuf *cbuf, float idnr) +{ + float *rect, *rs; + int x; + + rect= cbuf->rect; + rs= stackbuf->rect; + for(x= cbuf->x*cbuf->y - 1; x>=0; x--) + if(rect[x]==idnr) + rs[x]= 1.0f; + +} + + static void node_composit_exec_idmask(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { + RenderData *rd= data; + if(out[0]->hasoutput==0) return; @@ -77,7 +94,10 @@ static void node_composit_exec_idmask(void *data, bNode *node, bNodeStack **in, stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */; - do_idmask(stackbuf, cbuf, (float)node->custom1); + if(rd->scemode & R_FULL_SAMPLE) + do_idmask_fsa(stackbuf, cbuf, (float)node->custom1); + else + do_idmask(stackbuf, cbuf, (float)node->custom1); out[0]->data= stackbuf; } diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_zcombine.c b/source/blender/nodes/intern/CMP_nodes/CMP_zcombine.c index 29cf8f34d54..eb939100644 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_zcombine.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_zcombine.c @@ -45,6 +45,16 @@ static bNodeSocketType cmp_node_zcombine_out[]= { { -1, 0, "" } }; +static void do_zcombine(bNode *node, float *out, float *src1, float *z1, float *src2, float *z2) +{ + if(*z1 <= *z2) { + QUATCOPY(out, src1); + } + else { + QUATCOPY(out, src2); + } +} + static void do_zcombine_mask(bNode *node, float *out, float *z1, float *z2) { if(*z1 > *z2) { @@ -67,6 +77,8 @@ static void do_zcombine_add(bNode *node, float *out, float *col1, float *col2, f static void node_composit_exec_zcombine(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { + RenderData *rd= data; + /* stack order in: col z col z */ /* stack order out: col z */ if(out[0]->hasoutput==0) @@ -76,6 +88,16 @@ static void node_composit_exec_zcombine(void *data, bNode *node, bNodeStack **in if(in[0]->data==NULL) { return; } + else if(rd->scemode & R_FULL_SAMPLE) { + /* make output size of first input image */ + CompBuf *cbuf= in[0]->data; + CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs + + composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, + in[3]->data, in[3]->vec, do_zcombine, CB_RGBA, CB_VAL, CB_RGBA, CB_VAL); + + out[0]->data= stackbuf; + } else { /* make output size of first input image */ CompBuf *cbuf= in[0]->data; diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index de12f75300e..ddfe2c544ab 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -88,10 +88,11 @@ typedef struct RenderLayer { } RenderLayer; typedef struct RenderResult { + struct RenderResult *next, *prev; /* target image size */ int rectx, recty; - short crop, pad; + short crop, sample_nr; /* optional, 32 bits version of picture, used for ogl render and image curves */ int *rect32; @@ -113,7 +114,6 @@ typedef struct RenderResult { volatile RenderLayer *renlay; /* optional saved endresult on disk */ - char exrfile[FILE_MAXDIR]; void *exrhandle; /* for render results in Image, verify validity for sequences */ @@ -121,6 +121,7 @@ typedef struct RenderResult { } RenderResult; + typedef struct RenderStats { int totface, totvert, totstrand, tothalo, totlamp, totpart; short curfield, curblur, curpart, partsdone, convertdone; diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 8b5880ff507..e082225c5ea 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -157,6 +157,7 @@ typedef struct ShadeInput int xs, ys; /* pixel to be rendered */ int mask; /* subsample mask */ + int samplenr; /* sample counter, to detect if we should do shadow again */ int depth; /* 1 or larger on raytrace shading */ @@ -169,6 +170,7 @@ typedef struct ShadeInput /* from initialize, part or renderlayer */ short do_preview; /* for nodes, in previewrender */ short thread, sample; /* sample: ShadeSample array index */ + unsigned int lay; int layflag, passflag, combinedflag; struct Group *light_override; diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 16c46ec550f..de5c5485004 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -79,8 +79,8 @@ typedef struct RenderPart { struct RenderPart *next, *prev; - /* result of part rendering */ - RenderResult *result; + RenderResult *result; /* result of part rendering */ + ListBase fullresult; /* optional full sample buffers */ int *recto; /* object table for objects */ int *rectp; /* polygon index table */ @@ -113,6 +113,8 @@ struct Render RenderResult *result; /* if render with single-layer option, other rendered layers are stored here */ RenderResult *pushedresult; + /* a list of RenderResults, for fullsample */ + ListBase fullresult; /* window size, display rect, viewplane */ int winx, winy; diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h index f2fae7cca84..d569028fc50 100644 --- a/source/blender/render/intern/include/rendercore.h +++ b/source/blender/render/intern/include/rendercore.h @@ -93,6 +93,9 @@ void zbufshade_sss_tile(struct RenderPart *pa); void addps(struct ListBase *lb, long *rd, int obi, int facenr, int z, unsigned short mask); +int get_sample_layers(struct RenderPart *pa, struct RenderLayer *rl, struct RenderLayer **rlpp); + + /* -------- ray.c ------- */ extern void freeraytree(Render *re); diff --git a/source/blender/render/intern/include/shading.h b/source/blender/render/intern/include/shading.h index e3ffe5ef28f..e015309784d 100644 --- a/source/blender/render/intern/include/shading.h +++ b/source/blender/render/intern/include/shading.h @@ -40,7 +40,9 @@ struct ObjectInstanceRen obi; /* needed to calculate shadow and AO for an entire pixel */ typedef struct ShadeSample { - int tot; /* amount of shi in use, can be 1 for not FULL_OSA */ + int tot; /* amount of shi in use, can be 1 for not FULL_OSA */ + + RenderLayer *rlpp[RE_MAX_OSA]; /* fast lookup from sample to renderlayer (fullsample buf) */ /* could be malloced once */ ShadeInput shi[RE_MAX_OSA]; diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 7a8d151c738..6a8059bbdab 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -3704,7 +3704,7 @@ static void set_phong_threshold(ObjectRen *obr) } /* per face check if all samples should be taken. - if raytrace, do always for raytraced material, or when material full_osa set */ + if raytrace or multisample, do always for raytraced material, or when material full_osa set */ static void set_fullsample_flag(Render *re, ObjectRen *obr) { VlakRen *vlr; @@ -3718,7 +3718,8 @@ static void set_fullsample_flag(Render *re, ObjectRen *obr) for(a=obr->totvlak-1; a>=0; a--) { vlr= RE_findOrAddVlak(obr, a); - if(vlr->mat->mode & MA_FULL_OSA) vlr->flag |= R_FULL_OSA; + if(vlr->mat->mode & MA_FULL_OSA) + vlr->flag |= R_FULL_OSA; else if(trace) { if(vlr->mat->mode & MA_SHLESS); else if(vlr->mat->mode & (MA_RAYTRANSP|MA_RAYMIRROR)) diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index e4aa2326c0c..d3193a7eaaf 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -78,6 +78,7 @@ #include "envmap.h" #include "initrender.h" #include "shadbuf.h" +#include "pixelblending.h" #include "zbuf.h" @@ -195,6 +196,22 @@ void RE_FreeRenderResult(RenderResult *res) MEM_freeN(res); } +/* version that's compatible with fullsample buffers */ +static void free_render_result(ListBase *lb, RenderResult *rr) +{ + RenderResult *rrnext; + + for(; rr; rr= rrnext) { + rrnext= rr->next; + + if(lb && lb->first) + BLI_remlink(lb, rr); + + RE_FreeRenderResult(rr); + } +} + + /* all layers except the active one get temporally pushed away */ static void push_render_result(Render *re) { @@ -391,13 +408,18 @@ static int passtype_from_name(char *str) -static void render_unique_exr_name(Render *re, char *str) +static void render_unique_exr_name(Render *re, char *str, int sample) { char di[FILE_MAX], name[FILE_MAXFILE], fi[FILE_MAXFILE]; BLI_strncpy(di, G.sce, FILE_MAX); BLI_splitdirstring(di, fi); - sprintf(name, "%s_%s.exr", fi, re->scene->id.name+2); + + if(sample==0) + sprintf(name, "%s_%s.exr", fi, re->scene->id.name+2); + else + sprintf(name, "%s_%s%d.exr", fi, re->scene->id.name+2, sample); + if(G.background) BLI_make_file_string("/", str, "/tmp/", name); else @@ -421,17 +443,22 @@ static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channel IMB_exr_add_channel(rr->exrhandle, rl->name, get_pass_name(passtype, a), 0, 0, NULL); } else { + float *rect; + int x; + + rpass->rect= MEM_mapallocN(sizeof(float)*rectsize, typestr); + if(passtype==SCE_PASS_VECTOR) { - float *rect; - int x; - /* initialize to max speed */ - rect= rpass->rect= MEM_mapallocN(sizeof(float)*rectsize, typestr); + rect= rpass->rect; for(x= rectsize-1; x>=0; x--) rect[x]= PASS_VECTOR_MAX; } - else - rpass->rect= MEM_mapallocN(sizeof(float)*rectsize, typestr); + else if(passtype==SCE_PASS_Z) { + rect= rpass->rect; + for(x= rectsize-1; x>=0; x--) + rect[x]= 10e10; + } } } @@ -655,9 +682,8 @@ static void merge_render_result(RenderResult *rr, RenderResult *rrpart) } -static void save_render_result_tile(Render *re, RenderPart *pa) +static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart) { - RenderResult *rrpart= pa->result; RenderLayer *rlp; RenderPass *rpassp; int offs, partx, party; @@ -677,23 +703,23 @@ static void save_render_result_tile(Render *re, RenderPart *pa) if(rlp->rectf) { int a, xstride= 4; for(a=0; a<xstride; a++) - IMB_exr_set_channel(re->result->exrhandle, rlp->name, get_pass_name(SCE_PASS_COMBINED, a), - xstride, xstride*pa->rectx, rlp->rectf+a + xstride*offs); + IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(SCE_PASS_COMBINED, a), + xstride, xstride*rrpart->rectx, rlp->rectf+a + xstride*offs); } /* passes are allocated in sync */ for(rpassp= rlp->passes.first; rpassp; rpassp= rpassp->next) { int a, xstride= rpassp->channels; for(a=0; a<xstride; a++) - IMB_exr_set_channel(re->result->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a), - xstride, xstride*pa->rectx, rpassp->rect+a + xstride*offs); + IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a), + xstride, xstride*rrpart->rectx, rpassp->rect+a + xstride*offs); } } party= rrpart->tilerect.ymin + rrpart->crop; partx= rrpart->tilerect.xmin + rrpart->crop; - IMB_exrtile_write_channels(re->result->exrhandle, partx, party); + IMB_exrtile_write_channels(rr->exrhandle, partx, party); BLI_unlock_thread(LOCK_IMAGE); @@ -702,14 +728,17 @@ static void save_render_result_tile(Render *re, RenderPart *pa) static void save_empty_result_tiles(Render *re) { RenderPart *pa; + RenderResult *rr; - IMB_exrtile_clear_channels(re->result->exrhandle); + for(rr= re->result; rr; rr= rr->next) { + IMB_exrtile_clear_channels(rr->exrhandle); - for(pa= re->parts.first; pa; pa= pa->next) { - if(pa->ready==0) { - int party= pa->disprect.ymin - re->disprect.ymin + pa->crop; - int partx= pa->disprect.xmin - re->disprect.xmin + pa->crop; - IMB_exrtile_write_channels(re->result->exrhandle, partx, party); + for(pa= re->parts.first; pa; pa= pa->next) { + if(pa->ready==0) { + int party= pa->disprect.ymin - re->disprect.ymin + pa->crop; + int partx= pa->disprect.xmin - re->disprect.xmin + pa->crop; + IMB_exrtile_write_channels(rr->exrhandle, partx, party); + } } } } @@ -836,7 +865,7 @@ static void renderresult_add_names(RenderResult *rr) /* only for temp buffer files, makes exact copy of render result */ -static void read_render_result(Render *re) +static void read_render_result(Render *re, int sample) { RenderLayer *rl; RenderPass *rpass; @@ -847,13 +876,15 @@ static void read_render_result(Render *re) RE_FreeRenderResult(re->result); re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM); - render_unique_exr_name(re, str); + render_unique_exr_name(re, str, sample); if(IMB_exr_begin_read(exrhandle, str, &rectx, &recty)==0) { IMB_exr_close(exrhandle); printf("cannot read: %s\n", str); return; } + printf("read exr tmp file: %s\n", str); + if(rectx!=re->result->rectx || recty!=re->result->recty) { printf("error in reading render result\n"); } @@ -1060,7 +1091,7 @@ void RE_InitState(Render *re, RenderData *rd, int winx, int winy, rcti *disprect } if(re->rectx < 2 || re->recty < 2 || (BKE_imtype_is_movie(rd->imtype) && -(re->rectx < 16 || re->recty < 16) )) { + (re->rectx < 16 || re->recty < 16) )) { re->error("Image too small"); re->ok= 0; } @@ -1089,6 +1120,7 @@ void RE_InitState(Render *re, RenderData *rd, int winx, int winy, rcti *disprect } } +/* part of external api, not called for regular render pipeline */ void RE_SetDispRect (struct Render *re, rcti *disprect) { re->disprect= *disprect; @@ -1189,13 +1221,36 @@ static int render_display_draw_enabled(Render *re) return 1; } +/* allocate osa new results for samples */ +static RenderResult *new_full_sample_buffers(Render *re, ListBase *lb, rcti *partrct, int crop) +{ + int a; + + if(re->osa==0) + return new_render_result(re, partrct, crop, RR_USEMEM); + + for(a=0; a<re->osa; a++) { + RenderResult *rr= new_render_result(re, partrct, crop, RR_USEMEM); + BLI_addtail(lb, rr); + rr->sample_nr= a; + } + + return lb->first; +} + + +/* the main thread call, renders an entire part */ static void *do_part_thread(void *pa_v) { RenderPart *pa= pa_v; /* need to return nicely all parts on esc */ if(R.test_break()==0) { - pa->result= new_render_result(&R, &pa->disprect, pa->crop, RR_USEMEM); + + if(R.r.scemode & R_FULL_SAMPLE) + pa->result= new_full_sample_buffers(&R, &pa->fullresult, &pa->disprect, pa->crop); + else + pa->result= new_render_result(&R, &pa->disprect, pa->crop, RR_USEMEM); if(R.sss_points) zbufshade_sss_tile(pa); @@ -1205,8 +1260,13 @@ static void *do_part_thread(void *pa_v) zbufshade_tile(pa); /* merge too on break! */ - if(R.result->exrhandle) - save_render_result_tile(&R, pa); + if(R.result->exrhandle) { + RenderResult *rr, *rrpart; + + for(rr= R.result, rrpart= pa->result; rr && rrpart; rr= rr->next, rrpart= rrpart->next) + save_render_result_tile(rr, rrpart); + + } else if(render_display_draw_enabled(&R)) merge_render_result(R.result, pa->result); } @@ -1380,33 +1440,52 @@ static void print_part_stats(Render *re, RenderPart *pa) re->i.infostr= NULL; } +/* make osa new results for samples */ +static RenderResult *new_full_sample_buffers_exr(Render *re) +{ + int a; + + for(a=0; a<re->osa; a++) { + RenderResult *rr= new_render_result(re, &re->disprect, 0, 1); + BLI_addtail(&re->fullresult, rr); + rr->sample_nr= a; + } + + return re->fullresult.first; +} + static void threaded_tile_processor(Render *re) { ListBase threads; RenderPart *pa, *nextpa; - RenderResult *rr; rctf viewplane= re->viewplane; int rendering=1, counter= 1, drawtimer=0, hasdrawn, minx=0; - /* first step; the entire render result, or prepare exr buffer saving */ + /* first step; free the entire render result, make new, and/or prepare exr buffer saving */ RE_FreeRenderResult(re->result); - rr= re->result= new_render_result(re, &re->disprect, 0, re->r.scemode & R_EXR_TILE_FILE); - if(rr==NULL) + if(re->r.scemode & R_FULL_SAMPLE) + re->result= new_full_sample_buffers_exr(re); + else + re->result= new_render_result(re, &re->disprect, 0, re->r.scemode & R_EXR_TILE_FILE); + + if(re->result==NULL) return; + /* warning; no return here without closing exr file */ -// if(re->re->test_break()) -// return; initparts(re); - if(rr->exrhandle) { + if(re->result->exrhandle) { + RenderResult *rr; char str[FILE_MAX]; - render_unique_exr_name(re, str); + for(rr= re->result; rr; rr= rr->next) { + render_unique_exr_name(re, str, rr->sample_nr); - printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str); - IMB_exrtile_begin_write(rr->exrhandle, str, rr->rectx, rr->recty, rr->rectx/re->xparts, rr->recty/re->yparts); + printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str); + IMB_exrtile_begin_write(rr->exrhandle, str, rr->rectx, rr->recty, rr->rectx/re->xparts, rr->recty/re->yparts); + } } BLI_init_threads(&threads, do_part_thread, re->r.threads); @@ -1461,7 +1540,7 @@ static void threaded_tile_processor(Render *re) re->display_draw(pa->result, NULL); print_part_stats(re, pa); - RE_FreeRenderResult(pa->result); + free_render_result(&pa->fullresult, pa->result); pa->result= NULL; re->i.partsdone++; hasdrawn= 1; @@ -1485,11 +1564,20 @@ static void threaded_tile_processor(Render *re) } - if(rr->exrhandle) { + if(re->result->exrhandle) { + RenderResult *rr; + save_empty_result_tiles(re); - IMB_exr_close(rr->exrhandle); - rr->exrhandle= NULL; - read_render_result(re); + + for(rr= re->result; rr; rr= rr->next) { + IMB_exr_close(rr->exrhandle); + rr->exrhandle= NULL; + } + + free_render_result(&re->fullresult, re->result); + re->result= NULL; + + read_render_result(re, 0); } /* unset threadsafety */ @@ -1822,11 +1910,18 @@ static void do_render_fields_blur_3d(Render *re) static void render_scene(Render *re, Scene *sce, int cfra) { Render *resc= RE_NewRender(sce->id.name); + int winx= re->winx, winy= re->winy; sce->r.cfra= cfra; + /* exception: scene uses own size (unfinished code) */ + if(0) { + winx= (sce->r.size*sce->r.xsch)/100; + winy= (sce->r.size*sce->r.ysch)/100; + } + /* initial setup */ - RE_InitState(resc, &sce->r, re->winx, re->winy, &re->disprect); + RE_InitState(resc, &sce->r, winx, winy, &re->disprect); /* this to enable this scene to create speed vectors */ resc->r.scemode |= R_DOCOMP; @@ -1837,6 +1932,10 @@ static void render_scene(Render *re, Scene *sce, int cfra) /* ensure scene has depsgraph, base flags etc OK. Warning... also sets G.scene */ set_scene_bg(sce); + /* fullsample wants uniform osa levels */ + if(resc->r.scemode & R_FULL_SAMPLE) + resc->r.osa= resc->osa= re->osa; + /* copy callbacks */ resc->display_draw= re->display_draw; resc->test_break= re->test_break; @@ -1909,6 +2008,72 @@ static void render_composit_stats(char *str) R.i.infostr= NULL; } +/* reads all buffers, calls optional composite, merges in first result->rectf */ +static void do_merge_fullsample(Render *re, bNodeTree *ntree) +{ + float *rectf; + int sample; + + /* we accumulate in here */ + rectf= MEM_mapallocN(re->rectx*re->recty*sizeof(float)*4, "fullsample rgba"); + + for(sample=0; sample<re->osa; sample++) { + RenderResult rres; + int x, y, mask; + + /* set all involved renders on the samplebuffers (first was done by render itself) */ + if(sample) { + Render *re1; + for(re1= RenderList.first; re1; re1= re1->next) { + if(re1->r.scemode & R_FULL_SAMPLE) + read_render_result(re1, sample); + } + } + + /* composite */ + if(ntree) { + ntreeCompositTagRender(re->scene); + ntreeCompositTagAnimated(ntree); + + ntreeCompositExecTree(ntree, &re->r, G.background==0); + } + + /* ensure we get either composited result or the active layer */ + RE_GetResultImage(re, &rres); + + /* accumulate with filter, and clip */ + mask= (1<<sample); + for(y=1; y<re->recty-1; y++) { + float *rf= rectf + 4*y*re->rectx + 4; + float *col= rres.rectf + 4*y*re->rectx + 4; + + for(x=1; x<re->rectx-1; x++, rf+=4, col+=4) { + if(col[0]<0.0f) col[0]=0.0f; else if(col[0] > 1.0f) col[0]= 1.0f; + if(col[1]<0.0f) col[1]=0.0f; else if(col[1] > 1.0f) col[1]= 1.0f; + if(col[2]<0.0f) col[2]=0.0f; else if(col[2] > 1.0f) col[2]= 1.0f; + + add_filt_fmask(mask, col, rf, re->rectx); + } + } + + /* show stuff */ + if(sample!=re->osa-1) { + /* weak... the display callback wants an active renderlayer pointer... */ + re->result->renlay= render_get_active_layer(re, re->result); + re->display_draw(re->result, NULL); + } + + if(re->test_break()) + break; + } + + if(re->result->rectf) + MEM_freeN(re->result->rectf); + re->result->rectf= rectf; +} + + + /* returns fully composited render-result on given time step (in RenderData) */ static void do_render_composite_fields_blur_3d(Render *re) { @@ -1928,9 +2093,12 @@ static void do_render_composite_fields_blur_3d(Render *re) if(re->r.scemode & R_SINGLE_LAYER) pop_render_result(re); - if(!re->test_break() && ntree) { - ntreeCompositTagRender(re->scene); - ntreeCompositTagAnimated(ntree); + if(!re->test_break()) { + + if(ntree) { + ntreeCompositTagRender(re->scene); + ntreeCompositTagAnimated(ntree); + } if(re->r.scemode & R_DOCOMP) { /* checks if there are render-result nodes that need scene */ @@ -1943,11 +2111,19 @@ static void do_render_composite_fields_blur_3d(Render *re) /* in case it was never initialized */ R.stats_draw= re->stats_draw; - ntreeCompositExecTree(ntree, &re->r, G.background==0); + if(re->r.scemode & R_FULL_SAMPLE) + do_merge_fullsample(re, ntree); + else + ntreeCompositExecTree(ntree, &re->r, G.background==0); + ntree->stats_draw= NULL; ntree->test_break= NULL; } } + else + if(re->r.scemode & R_FULL_SAMPLE) + do_merge_fullsample(re, NULL); + } /* weak... the display callback wants an active renderlayer pointer... */ @@ -2101,14 +2277,20 @@ static int is_rendering_allowed(Render *re) if(re->r.scemode & R_EXR_TILE_FILE) { char str[FILE_MAX]; - render_unique_exr_name(re, str); + render_unique_exr_name(re, str, 0); if (BLI_is_writable(str)==0) { re->error("Can not save render buffers, check the temp default path"); return 0; } + /* no osa + fullsample won't work... */ + if(re->osa==0) + re->r.scemode &= ~R_FULL_SAMPLE; + } + else + re->r.scemode &= ~R_FULL_SAMPLE; /* clear to be sure */ if(re->r.scemode & R_DOCOMP) { if(re->scene->use_nodes) { @@ -2394,7 +2576,7 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra) /* note; repeated win/disprect calc... solve that nicer, also in compo */ -/* only temp file! */ +/* only the temp file! */ void RE_ReadRenderResult(Scene *scene, Scene *scenode) { Render *re; @@ -2426,7 +2608,7 @@ void RE_ReadRenderResult(Scene *scene, Scene *scenode) RE_InitState(re, &scene->r, winx, winy, &disprect); re->scene= scene; - read_render_result(re); + read_render_result(re, 0); } void RE_set_max_threads(int threads) diff --git a/source/blender/render/intern/source/pixelblending.c b/source/blender/render/intern/source/pixelblending.c index 119cceaf3c2..2c7d5e1d9cc 100644 --- a/source/blender/render/intern/source/pixelblending.c +++ b/source/blender/render/intern/source/pixelblending.c @@ -91,15 +91,6 @@ void addAlphaOverFloat(float *dest, float *source) void addAlphaUnderFloat(float *dest, float *source) { float mul; - - if( (-RE_EMPTY_COLOR_FLOAT < dest[3]) - && (dest[3] < RE_EMPTY_COLOR_FLOAT) ) { - dest[0] = source[0]; - dest[1] = source[1]; - dest[2] = source[2]; - dest[3] = source[3]; - return; - } mul= 1.0 - dest[3]; diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 220c06f1ede..dd5b96a50ca 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -348,12 +348,19 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, ShadeInput *shi, ShadeResult *shr) { RenderPass *rpass; + + /* combined rgb */ + add_filt_fmask(curmask, shr->combined, rl->rectf + 4*offset, rectx); for(rpass= rl->passes.first; rpass; rpass= rpass->next) { float *fp, *col= NULL; int pixsize= 3; switch(rpass->passtype) { + case SCE_PASS_Z: + fp= rpass->rect + offset; + *fp= -shi->co[2]; + break; case SCE_PASS_RGBA: col= shr->col; pixsize= 4; @@ -432,12 +439,20 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult *shr) { RenderPass *rpass; + float *fp; + + fp= rl->rectf + 4*offset; + QUATCOPY(fp, shr->combined); for(rpass= rl->passes.first; rpass; rpass= rpass->next) { - float *fp, *col= NULL, uvcol[3]; + float *col= NULL, uvcol[3]; int a, pixsize= 3; switch(rpass->passtype) { + case SCE_PASS_Z: + fp= rpass->rect + offset; + *fp= -shi->co[2]; + break; case SCE_PASS_RGBA: col= shr->col; pixsize= 4; @@ -497,26 +512,60 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult } } +int get_sample_layers(RenderPart *pa, RenderLayer *rl, RenderLayer **rlpp) +{ + + if(pa->fullresult.first) { + int sample, nr= BLI_findindex(&pa->result->layers, rl); + + for(sample=0; sample<R.osa; sample++) { + RenderResult *rr= BLI_findlink(&pa->fullresult, sample); + + rlpp[sample]= BLI_findlink(&rr->layers, nr); + } + return R.osa; + } + else { + rlpp[0]= rl; + return 1; + } +} + + /* only do sky, is default in the solid layer (shade_tile) btw */ -static void sky_tile(RenderPart *pa, float *pass) +static void sky_tile(RenderPart *pa, RenderLayer *rl) { - float col[4]; - int x, y; + RenderLayer *rlpp[RE_MAX_OSA]; + int x, y, od=0, totsample; if(R.r.alphamode!=R_ADDSKY) return; + totsample= get_sample_layers(pa, rl, rlpp); + for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++) { - for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, pass+=4) { - if(pass[3]<1.0f) { - if(pass[3]==0.0f) - shadeSkyPixel(pass, x, y); - else { - shadeSkyPixel(col, x, y); - addAlphaOverFloat(col, pass); - QUATCOPY(pass, col); + for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, od+=4) { + float col[4]; + int sample, done= 0; + + for(sample= 0; sample<totsample; sample++) { + float *pass= rlpp[sample]->rectf + od; + + if(pass[3]<1.0f) { + + if(done==0) { + shadeSkyPixel(col, x, y); + done= 1; + } + + if(pass[3]==0.0f) { + QUATCOPY(pass, col); + } + else { + addAlphaUnderFloat(pass, col); + } } - } + } } if(y&1) @@ -528,10 +577,9 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) { RenderResult *rr= pa->result; ShadeSample ssamp; - float *fcol, *rf, *rectf= rl->rectf; long *rd, *rectdaps= pa->rectdaps; int samp; - int x, y, seed, crop=0, offs=0, od, addpassflag; + int x, y, seed, crop=0, offs=0, od; if(R.test_break()) return; @@ -544,7 +592,6 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) /* general shader info, passes */ shade_sample_initialize(&ssamp, pa, rl); - addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED); /* occlusion caching */ if(R.occlusiontree) @@ -553,7 +600,6 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) /* filtered render, for now we assume only 1 filter size */ if(pa->crop) { crop= 1; - rectf+= 4*(pa->rectx + 1); rectdaps+= pa->rectx + 1; offs= pa->rectx + 1; } @@ -564,28 +610,35 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) rr->renlay= rl; for(y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++, rr->renrect.ymax++) { - rf= rectf; rd= rectdaps; od= offs; - for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, rd++, rf+=4, od++) { + for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, rd++, od++) { BLI_thread_srandom(pa->thread, seed++); if(*rd) { if(shade_samples(&ssamp, (PixStr *)(*rd), x, y)) { - for(samp=0; samp<ssamp.tot; samp++) { - - fcol= ssamp.shr[samp].combined; - add_filt_fmask(ssamp.shi[samp].mask, fcol, rf, pa->rectx); - - if(addpassflag) + + /* multisample buffers or filtered mask filling? */ + if(pa->fullresult.first) { + int a; + for(samp=0; samp<ssamp.tot; samp++) { + int smask= ssamp.shi[samp].mask; + for(a=0; a<R.osa; a++) { + int mask= 1<<a; + if(smask & mask) + add_passes(ssamp.rlpp[a], od, &ssamp.shi[samp], &ssamp.shr[samp]); + } + } + } + else { + for(samp=0; samp<ssamp.tot; samp++) add_filt_passes(rl, ssamp.shi[samp].mask, pa->rectx, od, &ssamp.shi[samp], &ssamp.shr[samp]); } } } } - rectf+= 4*pa->rectx; rectdaps+= pa->rectx; offs+= pa->rectx; @@ -918,97 +971,104 @@ void zbufshadeDA_tile(RenderPart *pa) /* transp layer */ if(R.flag & R_ZTRA) { if(rl->layflag & SCE_LAY_ZTRA) { - unsigned short *ztramask, *solidmask= NULL; /* 16 bits, MAX_OSA */ - - /* allocate, but not free here, for asynchronous display of this rect in main thread */ - rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer"); - - /* swap for live updates, and it is used in zbuf.c!!! */ - SWAP(float *, rl->acolrect, rl->rectf); - ztramask= zbuffer_transp_shade(pa, rl, rl->rectf, &psmlist); - SWAP(float *, rl->acolrect, rl->rectf); - - /* zbuffer transp only returns ztramask if there's solid rendered */ - if(ztramask) - solidmask= make_solid_mask(pa); - - if(ztramask && solidmask) { - unsigned short *sps= solidmask, *spz= ztramask; - unsigned short fullmask= (1<<R.osa)-1; - float *fcol= rl->rectf; float *acol= rl->acolrect; - int x; + if(pa->fullresult.first) { + zbuffer_transp_shade(pa, rl, rl->rectf, &psmlist); + } + else { + unsigned short *ztramask, *solidmask= NULL; /* 16 bits, MAX_OSA */ - for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4, sps++, spz++) { - if(*sps == fullmask) - addAlphaOverFloat(fcol, acol); - else - addAlphaOverFloatMask(fcol, acol, *sps, *spz); + /* allocate, but not free here, for asynchronous display of this rect in main thread */ + rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer"); + + /* swap for live updates, and it is used in zbuf.c!!! */ + SWAP(float *, rl->acolrect, rl->rectf); + ztramask= zbuffer_transp_shade(pa, rl, rl->rectf, &psmlist); + SWAP(float *, rl->acolrect, rl->rectf); + + /* zbuffer transp only returns ztramask if there's solid rendered */ + if(ztramask) + solidmask= make_solid_mask(pa); + + if(ztramask && solidmask) { + unsigned short *sps= solidmask, *spz= ztramask; + unsigned short fullmask= (1<<R.osa)-1; + float *fcol= rl->rectf; float *acol= rl->acolrect; + int x; + + for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4, sps++, spz++) { + if(*sps == fullmask) + addAlphaOverFloat(fcol, acol); + else + addAlphaOverFloatMask(fcol, acol, *sps, *spz); + } } - } - else { - float *fcol= rl->rectf; float *acol= rl->acolrect; - int x; - for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) { - addAlphaOverFloat(fcol, acol); + else { + float *fcol= rl->rectf; float *acol= rl->acolrect; + int x; + for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) { + addAlphaOverFloat(fcol, acol); + } } + if(solidmask) MEM_freeN(solidmask); + if(ztramask) MEM_freeN(ztramask); } - if(solidmask) MEM_freeN(solidmask); - if(ztramask) MEM_freeN(ztramask); } } /* strand rendering */ if((rl->layflag & SCE_LAY_STRAND) && R.totstrand) { - float *fcol, *scol; - unsigned short *strandmask, *solidmask= NULL; /* 16 bits, MAX_OSA */ - int x; - - /* allocate, but not free here, for asynchronous display of this rect in main thread */ - rl->scolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "strand layer"); + if(pa->fullresult.first) { + zbuffer_strands_shade(&R, pa, rl, rl->rectf); + } + else { + float *fcol, *scol; + unsigned short *strandmask, *solidmask= NULL; /* 16 bits, MAX_OSA */ + int x; + + /* allocate, but not free here, for asynchronous display of this rect in main thread */ + rl->scolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "strand layer"); - /* swap for live updates, and it is used in zbuf.c!!! */ - SWAP(float*, rl->scolrect, rl->rectf); - strandmask= zbuffer_strands_shade(&R, pa, rl, rl->rectf); - SWAP(float*, rl->scolrect, rl->rectf); + /* swap for live updates, and it is used in zbuf.c!!! */ + SWAP(float*, rl->scolrect, rl->rectf); + strandmask= zbuffer_strands_shade(&R, pa, rl, rl->rectf); + SWAP(float*, rl->scolrect, rl->rectf); - /* zbuffer strands only returns strandmask if there's solid rendered */ - if(strandmask) - solidmask= make_solid_mask(pa); - - if(strandmask && solidmask) { - unsigned short *sps= solidmask, *spz= strandmask; - unsigned short fullmask= (1<<R.osa)-1; + /* zbuffer strands only returns strandmask if there's solid rendered */ + if(strandmask) + solidmask= make_solid_mask(pa); + + if(strandmask && solidmask) { + unsigned short *sps= solidmask, *spz= strandmask; + unsigned short fullmask= (1<<R.osa)-1; - fcol= rl->rectf; scol= rl->scolrect; - for(x=pa->rectx*pa->recty; x>0; x--, scol+=4, fcol+=4, sps++, spz++) { - if(*sps == fullmask) + fcol= rl->rectf; scol= rl->scolrect; + for(x=pa->rectx*pa->recty; x>0; x--, scol+=4, fcol+=4, sps++, spz++) { + if(*sps == fullmask) + addAlphaOverFloat(fcol, scol); + else + addAlphaOverFloatMask(fcol, scol, *sps, *spz); + } + } + else { + fcol= rl->rectf; scol= rl->scolrect; + for(x=pa->rectx*pa->recty; x>0; x--, scol+=4, fcol+=4) addAlphaOverFloat(fcol, scol); - else - addAlphaOverFloatMask(fcol, scol, *sps, *spz); } - } - else { - fcol= rl->rectf; scol= rl->scolrect; - for(x=pa->rectx*pa->recty; x>0; x--, scol+=4, fcol+=4) - addAlphaOverFloat(fcol, scol); - } - if(solidmask) MEM_freeN(solidmask); - if(strandmask) MEM_freeN(strandmask); + if(solidmask) MEM_freeN(solidmask); + if(strandmask) MEM_freeN(strandmask); + } } /* sky before edge */ if(rl->layflag & SCE_LAY_SKY) - sky_tile(pa, rl->rectf); + sky_tile(pa, rl); /* extra layers */ if(rl->layflag & SCE_LAY_EDGE) if(R.r.mode & R_EDGE) edge_enhance_add(pa, rl->rectf, edgerect); - if(rl->passflag & SCE_PASS_Z) - convert_zbuf_to_distbuf(pa, rl); - if(rl->passflag & SCE_PASS_VECTOR) reset_sky_speed(pa, rl); @@ -1046,7 +1106,6 @@ void zbufshade_tile(RenderPart *pa) RenderLayer *rl; PixStr ps; float *edgerect= NULL; - int addpassflag; /* fake pixel struct, to comply to osa render */ ps.next= NULL; @@ -1061,7 +1120,6 @@ void zbufshade_tile(RenderPart *pa) /* general shader info, passes */ shade_sample_initialize(&ssamp, pa, rl); - addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED); zbuffer_solid(pa, rl, NULL, NULL); @@ -1104,11 +1162,8 @@ void zbufshade_tile(RenderPart *pa) ps.facenr= *rp; ps.z= *rz; if(shade_samples(&ssamp, &ps, x, y)) { - QUATCOPY(fcol, ssamp.shr[0].combined); - - /* passes */ - if(addpassflag) - add_passes(rl, offs, ssamp.shi, ssamp.shr); + /* combined and passes */ + add_passes(rl, offs, ssamp.shi, ssamp.shr); } } } @@ -1177,7 +1232,7 @@ void zbufshade_tile(RenderPart *pa) /* sky before edge */ if(rl->layflag & SCE_LAY_SKY) - sky_tile(pa, rl->rectf); + sky_tile(pa, rl); if(!R.test_break()) { if(rl->layflag & SCE_LAY_EDGE) @@ -1185,9 +1240,6 @@ void zbufshade_tile(RenderPart *pa) edge_enhance_add(pa, rl->rectf, edgerect); } - if(rl->passflag & SCE_PASS_Z) - convert_zbuf_to_distbuf(pa, rl); - if(rl->passflag & SCE_PASS_VECTOR) reset_sky_speed(pa, rl); diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index 3a8b0cca7fc..a0554cbaa56 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -31,6 +31,7 @@ #include "MTC_matrixops.h" #include "BLI_arithb.h" +#include "BLI_blenlib.h" #include "DNA_curve_types.h" #include "DNA_group_types.h" @@ -1214,8 +1215,9 @@ void shade_input_initialize(ShadeInput *shi, RenderPart *pa, RenderLayer *rl, in shi->combinedflag= ~rl->pass_xor; shi->mat_override= rl->mat_override; shi->light_override= rl->light_override; - +// shi->rl= rl; /* note shi.depth==0 means first hit, not raytracing */ + } /* initialize per part, not per pixel! */ @@ -1230,6 +1232,8 @@ void shade_sample_initialize(ShadeSample *ssamp, RenderPart *pa, RenderLayer *rl memset(&ssamp->shr[a], 0, sizeof(ShadeResult)); } + get_sample_layers(pa, rl, ssamp->rlpp); + ssamp->samplenr= 0; /* counter, detect shadow-reuse for shaders */ } @@ -1279,7 +1283,8 @@ void shade_samples_fill_with_ps(ShadeSample *ssamp, PixStr *ps, int x, int y) shade_input_copy_triangle(shi, shi-1); shi->mask= (1<<samp); - shi->samplenr= ssamp->samplenr++; +// shi->rl= ssamp->rlpp[samp]; + shi->samplenr= ssamp->samplenr++; /* this counter is not being reset per pixel */ shade_input_set_viewco(shi, xs, ys, (float)ps->z); shade_input_set_uv(shi); shade_input_set_normals(shi); diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c index bf58c023998..b1cba27ba9b 100644 --- a/source/blender/render/intern/source/strand.c +++ b/source/blender/render/intern/source/strand.c @@ -913,12 +913,16 @@ static void zbuffer_strands_filter(Render *re, RenderPart *pa, RenderLayer *rl, { RenderResult *rr= pa->result; ShadeResult *shr, *shrrect= spart->result; + RenderLayer *rl_pp[RE_MAX_OSA]; float *passrect= pass, alpha, sampalpha; long *rdrect; int osa, x, y, a, crop= 0, offs=0, od; osa= (re->osa? re->osa: 1); sampalpha= 1.0f/osa; + + /* only used for multisample buffers */ + get_sample_layers(pa, rl, rl_pp); /* filtered render, for now we assume only 1 filter size */ if(pa->crop) { @@ -933,7 +937,7 @@ static void zbuffer_strands_filter(Render *re, RenderPart *pa, RenderLayer *rl, /* zero alpha pixels get speed vector max again */ if(spart->addpassflag & SCE_PASS_VECTOR) if(rl->layflag & SCE_LAY_SOLID) - reset_sky_speedvectors(pa, rl, rl->scolrect); + reset_sky_speedvectors(pa, rl, rl->scolrect?rl->scolrect:rl->rectf); /* scolrect==NULL for multisample */ /* init scanline updates */ rr->renrect.ymin= 0; @@ -954,26 +958,44 @@ static void zbuffer_strands_filter(Render *re, RenderPart *pa, RenderLayer *rl, else { alpha= 0.0f; - if(re->osa == 0) { - addAlphaUnderFloat(pass, shr->combined); - } - else { - /* note; cannot use pass[3] for alpha due to filtermask */ + if(pa->fullresult.first) { for(a=0; a<re->osa; a++) { - add_filt_fmask(1<<a, shr[a].combined, pass, rr->rectx); - alpha += shr[a].combined[3]; + alpha= shr[a].combined[3]; + if(alpha!=0.0f) { + RenderLayer *rl= rl_pp[a]; + + addAlphaOverFloat(rl->rectf + 4*od, shr[a].combined); + + add_transp_passes(rl, od, shr, alpha); + if(spart->addpassflag & SCE_PASS_VECTOR) + add_transp_speed(rl, od, shr[a].winspeed, alpha, rdrect); + } } + } + else { + + if(re->osa == 0) { + addAlphaUnderFloat(pass, shr->combined); + } + else { + /* note; cannot use pass[3] for alpha due to filtermask */ + for(a=0; a<re->osa; a++) { + add_filt_fmask(1<<a, shr[a].combined, pass, rr->rectx); + alpha += shr[a].combined[3]; + } + } - if(spart->addpassflag) { - alpha *= sampalpha; + if(spart->addpassflag) { + alpha *= sampalpha; - /* merge all in one, and then add */ - merge_transp_passes(rl, shr); - add_transp_passes(rl, od, shr, alpha); + /* merge all in one, and then add */ + merge_transp_passes(rl, shr); + add_transp_passes(rl, od, shr, alpha); - if(spart->addpassflag & SCE_PASS_VECTOR) - add_transp_speed(rl, od, shr->winspeed, alpha, rdrect); + if(spart->addpassflag & SCE_PASS_VECTOR) + add_transp_speed(rl, od, shr->winspeed, alpha, rdrect); + } } } } @@ -1203,7 +1225,7 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r zbuf_free_span(&zspan); - if(!(re->osa && (rl->layflag & SCE_LAY_SOLID))) { + if( !(re->osa && (rl->layflag & SCE_LAY_SOLID)) || (pa->fullresult.first)) { MEM_freeN(spart.mask); spart.mask= NULL; } diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 6b103d4fce2..8aa2e06714c 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -3793,7 +3793,7 @@ void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf) #define MAX_ZROW 2000 -/* main render call to fill in pass the full transparent layer */ +/* main render call to do the z-transparent layer */ /* returns a mask, only if a) transp rendered and b) solid was rendered */ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass, ListBase *psmlist) { @@ -3851,13 +3851,13 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas ISB_create(pa, APixbuf); /* masks, to have correct alpha combine */ - if(R.osa && (rl->layflag & SCE_LAY_SOLID)) + if(R.osa && (rl->layflag & SCE_LAY_SOLID) && pa->fullresult.first==NULL) ztramask= MEM_callocN(pa->rectx*pa->recty*sizeof(short), "ztramask"); /* zero alpha pixels get speed vector max again */ if(addpassflag & SCE_PASS_VECTOR) if(rl->layflag & SCE_LAY_SOLID) - reset_sky_speedvectors(pa, rl, rl->acolrect); + reset_sky_speedvectors(pa, rl, rl->acolrect?rl->acolrect:rl->rectf); /* if acolrect is set we use it */ /* filtered render, for now we assume only 1 filter size */ if(pa->crop) { @@ -3967,21 +3967,39 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas } } - /* note; cannot use pass[3] for alpha due to filtermask */ - for(a=0; a<R.osa; a++) { - add_filt_fmask(1<<a, samp_shr[a].combined, pass, rr->rectx); - alpha+= samp_shr[a].combined[3]; + /* multisample buffers or filtered mask filling? */ + if(pa->fullresult.first) { + for(a=0; a<R.osa; a++) { + alpha= samp_shr[a].combined[3]; + if(alpha!=0.0f) { + RenderLayer *rl= ssamp.rlpp[a]; + + addAlphaOverFloat(rl->rectf + 4*od, samp_shr[a].combined); + + add_transp_passes(rl, od, samp_shr, alpha); + if(addpassflag & SCE_PASS_VECTOR) + add_transp_speed(rl, od, samp_shr[a].winspeed, alpha, rdrect); + } + } } - - if(addpassflag) { - alpha*= sampalpha; + else { + + /* note; cannot use pass[3] for alpha due to filtermask */ + for(a=0; a<R.osa; a++) { + add_filt_fmask(1<<a, samp_shr[a].combined, pass, rr->rectx); + alpha+= samp_shr[a].combined[3]; + } - /* merge all in one, and then add */ - merge_transp_passes(rl, samp_shr); - add_transp_passes(rl, od, samp_shr, alpha); + if(addpassflag) { + alpha*= sampalpha; + + /* merge all in one, and then add */ + merge_transp_passes(rl, samp_shr); + add_transp_passes(rl, od, samp_shr, alpha); - if(addpassflag & SCE_PASS_VECTOR) - add_transp_speed(rl, od, samp_shr[0].winspeed, alpha, rdrect); + if(addpassflag & SCE_PASS_VECTOR) + add_transp_speed(rl, od, samp_shr[0].winspeed, alpha, rdrect); + } } } } diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index 680c26b403f..965893ad344 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -1837,28 +1837,27 @@ static void render_panel_output(void) uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, R_TOUCH, B_NOP, "Touch", 10, 142, 50, 20, &G.scene->r.mode, 0.0, 0.0, 0, 0, "Create an empty file before rendering each frame, remove if cancelled (and empty)"); + uiDefButBitI(block, TOG, R_TOUCH, B_NOP, "Touch", 10, 142, 50, 20, &G.scene->r.mode, 0.0, 0.0, 0, 0, "Create an empty file before rendering each frame, remove if cancelled (and empty)"); uiDefButBitI(block, TOG, R_NO_OVERWRITE, B_NOP, "No Overwrite", 60, 142, 90, 20, &G.scene->r.mode, 0.0, 0.0, 0, 0, "Skip rendering frames when the file exists (image output only)"); uiBlockEndAlign(block); + uiDefButBitS(block, TOG, R_BACKBUF, B_NOP,"Backbuf", 160, 142, 80, 20, &G.scene->r.bufflag, 0, 0, 0, 0, "Enable/Disable use of Backbuf image"); /* SET BUTTON */ uiBlockBeginAlign(block); id= (ID *)G.scene->set; IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->scene), id, &(G.buts->menunr)); if(strp[0]) - uiDefButS(block, MENU, B_SETBROWSE, strp, 10, 114, 20, 20, &(G.buts->menunr), 0, 0, 0, 0, "Scene to link as a Set"); + uiDefButS(block, MENU, B_SETBROWSE, strp, 10, 114, 20, 20, &(G.buts->menunr), 0, 0, 0, 0, "Scene to link as a Set"); MEM_freeN(strp); if(G.scene->set) { uiSetButLock(1, NULL); - uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, B_NOP, "", 31, 120, 100, 20, &(G.scene->set), "Name of the Set"); + uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, B_NOP, "", 31, 114, 100, 20, &(G.scene->set), "Name of the Set"); uiClearButLock(); - uiDefIconBut(block, BUT, B_CLEARSET, ICON_X, 132, 120, 20, 20, 0, 0, 0, 0, 0, "Remove Set link"); + uiDefIconBut(block, BUT, B_CLEARSET, ICON_X, 132, 114, 20, 20, 0, 0, 0, 0, 0, "Remove Set link"); } uiBlockEndAlign(block); - uiBlockSetCol(block, TH_BUT_SETTING1); - uiDefButBitS(block, TOG, R_BACKBUF, B_NOP,"Backbuf", 10, 89, 80, 20, &G.scene->r.bufflag, 0, 0, 0, 0, "Enable/Disable use of Backbuf image"); uiDefButS(block, NUM, B_NOP, "Threads:", 10, 63, 100, 20, &G.scene->r.threads, 1, BLENDER_MAX_THREADS, 0, 0, "Amount of threads for render (takes advantage of multi-core and multi-processor computers)"); uiBlockSetCol(block, TH_AUTO); @@ -1866,9 +1865,12 @@ static void render_panel_output(void) for(b=2; b>=0; b--) for(a=0; a<3; a++) uiDefButBitS(block, TOG, 1<<(3*b+a), 800,"", (short)(10+18*a),(short)(10+14*b),16,12, &G.winpos, 0, 0, 0, 0, "Render window placement on screen"); - uiBlockEndAlign(block); - uiDefButBitS(block, TOG, R_EXR_TILE_FILE, B_NOP, "Save Buffers", 72, 31, 120, 19, &G.scene->r.scemode, 0.0, 0.0, 0, 0, "Save the tiles for all RenderLayers and used SceneNodes to files, to save memory"); + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG, R_EXR_TILE_FILE, B_REDR, "Save Buffers", 72, 31, 120, 19, &G.scene->r.scemode, 0.0, 0.0, 0, 0, "Save the tiles for all RenderLayers and used SceneNodes to files, to save memory"); + if(G.scene->r.scemode & R_EXR_TILE_FILE) + uiDefButBitS(block, TOG, R_FULL_SAMPLE, B_REDR, "FullSample", 192, 31, 118, 19, &G.scene->r.scemode, 0.0, 0.0, 0, 0, "Saves for every OSA sample the entire RenderLayer results"); + uiBlockEndAlign(block); uiDefButS(block, MENU, B_REDR, "Render Display %t|Render Window %x1|Image Editor %x0|Full Screen %x2", 72, 10, 120, 19, &G.displaymode, 0.0, (float)R_DISPLAYWIN, 0, 0, "Sets render output display"); @@ -1876,12 +1878,12 @@ static void render_panel_output(void) uiDefButBitS(block, TOG, R_EXTENSION, B_NOP, "Extensions", 205, 10, 105, 19, &G.scene->r.scemode, 0.0, 0.0, 0, 0, "Adds filetype extensions to the filename when rendering animations"); /* Dither control */ - uiDefButF(block, NUM,B_DIFF, "Dither:", 205,31,105,19, &G.scene->r.dither_intensity, 0.0, 2.0, 0, 0, "The amount of dithering noise present in the output image (0.0 = no dithering)"); + uiDefButF(block, NUM,B_DIFF, "Dither:", 10,89,100,19, &G.scene->r.dither_intensity, 0.0, 2.0, 0, 0, "The amount of dithering noise present in the output image (0.0 = no dithering)"); /* Toon shading buttons */ uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, R_EDGE, B_NOP,"Edge", 100, 89, 70, 20, &G.scene->r.mode, 0, 0, 0, 0, "Enable Toon Edge-enhance"); - uiDefBlockBut(block, edge_render_menu, NULL, "Edge Settings", 170, 89, 140, 20, "Display Edge settings"); + uiDefButBitI(block, TOG, R_EDGE, B_NOP,"Edge", 115, 89, 60, 20, &G.scene->r.mode, 0, 0, 0, 0, "Enable Toon Edge-enhance"); + uiDefBlockBut(block, edge_render_menu, NULL, "Edge Settings", 175, 89, 135, 20, "Display Edge settings"); uiBlockEndAlign(block); uiBlockBeginAlign(block); @@ -1957,7 +1959,10 @@ static void render_panel_render(void) #endif /* disable yafray */ uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, R_OSA, B_DIFF, "OSA", 369,109,122,20,&G.scene->r.mode, 0, 0, 0, 0, "Enables Oversampling (Anti-aliasing)"); + if((G.scene->r.scemode & R_FULL_SAMPLE) && (G.scene->r.scemode & R_EXR_TILE_FILE)) + uiDefButBitI(block, TOG, R_OSA, B_DIFF, "FSA", 369,109,122,20,&G.scene->r.mode, 0, 0, 0, 0, "Saves all samples, then composites, and then merges (for best Anti-aliasing)"); + else + uiDefButBitI(block, TOG, R_OSA, B_DIFF, "OSA", 369,109,122,20,&G.scene->r.mode, 0, 0, 0, 0, "Enables Oversampling (Anti-aliasing)"); uiDefButS(block, ROW,B_DIFF,"5", 369,88,29,20,&G.scene->r.osa,2.0,5.0, 0, 0, "Render 5 samples per pixel for smooth edges (Fast)"); uiDefButS(block, ROW,B_DIFF,"8", 400,88,29,20,&G.scene->r.osa,2.0,8.0, 0, 0, "Render 8 samples per pixel for smooth edges (Recommended)"); uiDefButS(block, ROW,B_DIFF,"11", 431,88,29,20,&G.scene->r.osa,2.0,11.0, 0, 0, "Render 11 samples per pixel for smooth edges (High Quality)"); diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index be307a649b3..76a4f024f26 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -1175,13 +1175,13 @@ void uiblock_image_panel(uiBlock *block, Image **ima_pp, ImageUser *iuser, /* fields */ uiBlockBeginAlign(block); - but= uiDefButBitS(block, TOG, IMA_FIELDS, imagechanged, "Fields", 10, 90, 65, 20, &ima->flag, 0, 0, 0, 0, "Click to enable use of fields in Image"); + but= uiDefButBitS(block, TOG, IMA_FIELDS, imagechanged, "Fields", 10, 70, 65, 20, &ima->flag, 0, 0, 0, 0, "Click to enable use of fields in Image"); uiButSetFunc(but, image_field_test, ima, iuser); - uiDefButBitS(block, TOG, IMA_STD_FIELD, B_NOP, "Odd", 75, 90, 45, 20, &ima->flag, 0, 0, 0, 0, "Standard Field Toggle"); + uiDefButBitS(block, TOG, IMA_STD_FIELD, B_NOP, "Odd", 75, 70, 45, 20, &ima->flag, 0, 0, 0, 0, "Standard Field Toggle"); uiBlockSetFunc(block, image_reload_cb, ima, iuser); - uiDefButBitS(block, TOG, IMA_ANTIALI, B_NOP, "Anti", 10, 70, 45, 20, &ima->flag, 0, 0, 0, 0, "Toggles Image anti-aliasing, only works with solid colors"); - uiDefButBitS(block, TOG, IMA_DO_PREMUL, imagechanged, "Premul", 55, 70, 65, 20, &ima->flag, 0, 0, 0, 0, "Toggles premultiplying alpha"); + uiDefButBitS(block, TOG, IMA_ANTIALI, B_NOP, "Anti", 10, 50, 45, 20, &ima->flag, 0, 0, 0, 0, "Toggles Image anti-aliasing, only works with solid colors"); + uiDefButBitS(block, TOG, IMA_DO_PREMUL, imagechanged, "Premul", 55, 50, 65, 20, &ima->flag, 0, 0, 0, 0, "Toggles premultiplying alpha"); uiBlockEndAlign(block); if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { @@ -1189,21 +1189,21 @@ void uiblock_image_panel(uiBlock *block, Image **ima_pp, ImageUser *iuser, uiBlockBeginAlign(block); uiBlockSetFunc(block, image_user_change, iuser, NULL); - uiDefButBitS(block, TOG, IMA_ANIM_ALWAYS, B_NOP, "Auto Refresh", 120, 90, 190, 20, &iuser->flag, 0, 0, 0, 0, "Always refresh Image on frame changes"); + uiDefButBitS(block, TOG, IMA_ANIM_ALWAYS, B_NOP, "Auto Refresh", 120, 70, 190, 20, &iuser->flag, 0, 0, 0, 0, "Always refresh Image on frame changes"); if(ima->anim) { - uiDefButI(block, NUM, imagechanged, str, 120, 70,170, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use"); - but= uiDefBut(block, BUT, redraw, "<", 290, 70, 20, 20, 0, 0, 0, 0, 0, "Copies number of frames in movie file to Frames: button"); + uiDefButI(block, NUM, imagechanged, str, 120, 50,170, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use"); + but= uiDefBut(block, BUT, redraw, "<", 290, 50, 20, 20, 0, 0, 0, 0, 0, "Copies number of frames in movie file to Frames: button"); uiButSetFunc(but, set_frames_cb, ima, iuser); } else - uiDefButI(block, NUM, imagechanged, str, 120, 70,190, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use"); + uiDefButI(block, NUM, imagechanged, str, 120, 50,190, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use"); - uiDefButI(block, NUM, imagechanged, "Offs:", 120,50,100,20, &iuser->offset, -MAXFRAMEF, MAXFRAMEF, 0, 0, "Offsets the number of the frame to use in the animation"); - uiDefButS(block, NUM, imagechanged, "Fie/Ima:", 220,50,90,20, &iuser->fie_ima, 1.0, 200.0, 0, 0, "The number of fields per rendered frame (2 fields is 1 image)"); + uiDefButI(block, NUM, imagechanged, "Offs:", 120,30,100,20, &iuser->offset, -MAXFRAMEF, MAXFRAMEF, 0, 0, "Offsets the number of the frame to use in the animation"); + uiDefButS(block, NUM, imagechanged, "Fie/Ima:", 220,30,90,20, &iuser->fie_ima, 1.0, 200.0, 0, 0, "The number of fields per rendered frame (2 fields is 1 image)"); - uiDefButI(block, NUM, imagechanged, "StartFr:", 120,30,100,20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Sets the global starting frame of the movie"); - uiDefButS(block, TOG, imagechanged, "Cyclic", 220,30,90,20, &iuser->cycl, 0.0, 1.0, 0, 0, "Cycle the images in the movie"); + uiDefButI(block, NUM, imagechanged, "StartFr:", 120,10,100,20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Sets the global starting frame of the movie"); + uiDefButS(block, TOG, imagechanged, "Cyclic", 220,10,90,20, &iuser->cycl, 0.0, 1.0, 0, 0, "Cycle the images in the movie"); uiBlockSetFunc(block, NULL, iuser, NULL); } @@ -1211,9 +1211,9 @@ void uiblock_image_panel(uiBlock *block, Image **ima_pp, ImageUser *iuser, uiBlockBeginAlign(block); uiBlockSetFunc(block, image_generated_change_cb, ima, iuser); - uiDefButS(block, NUM, imagechanged, "SizeX:", 120,90,100,20, &ima->gen_x, 1.0, 5000.0, 0, 0, "Image size x"); - uiDefButS(block, NUM, imagechanged, "SizeY:", 220,90,90,20, &ima->gen_y, 1.0, 5000.0, 0, 0, "Image size y"); - uiDefButS(block, TOG, imagechanged, "UV Test grid",120,70,190,20, &ima->gen_type, 0.0, 1.0, 0, 0, ""); + uiDefButS(block, NUM, imagechanged, "SizeX:", 120,70,100,20, &ima->gen_x, 1.0, 5000.0, 0, 0, "Image size x"); + uiDefButS(block, NUM, imagechanged, "SizeY:", 220,70,90,20, &ima->gen_y, 1.0, 5000.0, 0, 0, "Image size y"); + uiDefButS(block, TOG, imagechanged, "UV Test grid",120,50,190,20, &ima->gen_type, 0.0, 1.0, 0, 0, ""); uiBlockSetFunc(block, NULL, NULL, NULL); } } |