diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 0961c349fc3..05019001155 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -383,7 +383,6 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel): sub.prop(cscene, "use_progressive_refine") subsub = sub.column(align=True) - subsub.enabled = not rd.use_border subsub.prop(rd, "use_save_buffers") col = split.column(align=True) diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index 4ea1c3a5cc7..794ef5189d6 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -193,7 +193,6 @@ class RENDER_PT_antialiasing(RenderButtonsPanel, Panel): col = split.column() col.row().prop(rd, "antialiasing_samples", expand=True) sub = col.row() - sub.enabled = not rd.use_border sub.prop(rd, "use_full_sample") col = split.column() @@ -280,7 +279,7 @@ class RENDER_PT_performance(RenderButtonsPanel, Panel): col = split.column() col.label(text="Memory:") sub = col.column() - sub.enabled = not (rd.use_border or rd.use_full_sample) + sub.enabled = not rd.use_full_sample sub.prop(rd, "use_save_buffers") sub = col.column() sub.active = rd.use_compositing diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 2943d74f9be..d1f8c4e5bed 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -841,21 +841,12 @@ static int rna_RenderSettings_save_buffers_get(PointerRNA *ptr) RenderData *rd = (RenderData *)ptr->data; Scene *scene = (Scene *)ptr->id.data; - if (rd->mode & R_BORDER) - return 0; - else if (!BKE_scene_use_new_shading_nodes(scene)) + if (!BKE_scene_use_new_shading_nodes(scene)) return (rd->scemode & (R_EXR_TILE_FILE | R_FULL_SAMPLE)) != 0; else return (rd->scemode & R_EXR_TILE_FILE) != 0; } -static int rna_RenderSettings_full_sample_get(PointerRNA *ptr) -{ - RenderData *rd = (RenderData *)ptr->data; - - return (rd->scemode & R_FULL_SAMPLE) && !(rd->mode & R_BORDER); -} - static void rna_ImageFormatSettings_file_format_set(PointerRNA *ptr, int value) { ImageFormatData *imf = (ImageFormatData *)ptr->data; @@ -5768,7 +5759,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop = RNA_def_property(srna, "use_full_sample", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_FULL_SAMPLE); - RNA_def_property_boolean_funcs(prop, "rna_RenderSettings_full_sample_get", NULL); RNA_def_property_ui_text(prop, "Full Sample", "Save for every anti-aliasing sample the entire RenderLayer results " "(this solves anti-aliasing issues with compositing)"); diff --git a/source/blender/render/intern/include/pixelblending.h b/source/blender/render/intern/include/pixelblending.h index 19759bf3e97..17a872a0676 100644 --- a/source/blender/render/intern/include/pixelblending.h +++ b/source/blender/render/intern/include/pixelblending.h @@ -38,7 +38,7 @@ */ void add_filt_fmask(unsigned int mask, const float col[4], float *rowbuf, int row_w); void add_filt_fmask_pixsize(unsigned int mask, float *in, float *rowbuf, int row_w, int pixsize); -void add_filt_fmask_coord(float filt[3][3], const float col[4], float *rowbuf, int row_w, int col_h, int x, int y); +void add_filt_fmask_coord(float filt[3][3], const float col[4], float *rowbuf, int row_stride, int x, int y, rcti *mask); void mask_array(unsigned int mask, float filt[3][3]); /** diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 7af63051dfe..6c5cc295fce 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -634,12 +634,6 @@ static int check_mode_full_sample(RenderData *rd) #ifdef WITH_OPENEXR if (scemode & R_FULL_SAMPLE) scemode |= R_EXR_TILE_FILE; /* enable automatic */ - - /* Until use_border is made compatible with save_buffers/full_sample, render without the later instead of not rendering at all.*/ - if (rd->mode & R_BORDER) { - scemode &= ~(R_EXR_TILE_FILE | R_FULL_SAMPLE); - } - #else /* can't do this without openexr support */ scemode &= ~(R_EXR_TILE_FILE | R_FULL_SAMPLE); @@ -1829,6 +1823,53 @@ static void render_result_disprect_to_full_resolution(Render *re) re->recty = re->winy; } +static void render_result_uncrop(Render *re) +{ + /* when using border render with crop disabled, insert render result into + * full size with black pixels outside */ + if (re->result && (re->r.mode & R_BORDER)) { + if ((re->r.mode & R_CROP) == 0) { + RenderResult *rres; + + /* backup */ + const rcti orig_disprect = re->disprect; + const int orig_rectx = re->rectx, orig_recty = re->recty; + + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + + /* sub-rect for merge call later on */ + re->result->tilerect = re->disprect; + + /* weak is: it chances disprect from border */ + render_result_disprect_to_full_resolution(re); + + rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); + + render_result_merge(rres, re->result); + render_result_free(re->result); + re->result = rres; + + /* weak... the display callback wants an active renderlayer pointer... */ + re->result->renlay = render_get_active_layer(re, re->result); + + BLI_rw_mutex_unlock(&re->resultmutex); + + re->display_init(re->dih, re->result); + re->display_update(re->duh, re->result, NULL); + + /* restore the disprect from border */ + re->disprect = orig_disprect; + re->rectx = orig_rectx; + re->recty = orig_recty; + } + else { + /* set offset (again) for use in compositor, disprect was manipulated. */ + re->result->xof = 0; + re->result->yof = 0; + } + } +} + /* main render routine, no compositing */ static void do_render_fields_blur_3d(Render *re) { @@ -1851,49 +1892,7 @@ static void do_render_fields_blur_3d(Render *re) do_render_3d(re); /* when border render, check if we have to insert it in black */ - if (re->result) { - if (re->r.mode & R_BORDER) { - if ((re->r.mode & R_CROP) == 0) { - RenderResult *rres; - - /* backup */ - const rcti orig_disprect = re->disprect; - const int orig_rectx = re->rectx, orig_recty = re->recty; - - BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - - /* sub-rect for merge call later on */ - re->result->tilerect = re->disprect; - - /* weak is: it chances disprect from border */ - render_result_disprect_to_full_resolution(re); - - rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); - - render_result_merge(rres, re->result); - render_result_free(re->result); - re->result = rres; - - /* weak... the display callback wants an active renderlayer pointer... */ - re->result->renlay = render_get_active_layer(re, re->result); - - BLI_rw_mutex_unlock(&re->resultmutex); - - re->display_init(re->dih, re->result); - re->display_update(re->duh, re->result, NULL); - - /* restore the disprect from border */ - re->disprect = orig_disprect; - re->rectx = orig_rectx; - re->recty = orig_recty; - } - else { - /* set offset (again) for use in compositor, disprect was manipulated. */ - re->result->xof = 0; - re->result->yof = 0; - } - } - } + render_result_uncrop(re); } @@ -2292,6 +2291,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) { ListBase *rectfs; RenderView *rv; + rcti filter_mask = re->disprect; float *rectf, filt[3][3]; int x, y, sample; int nr, numviews; @@ -2317,7 +2317,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) rv = MEM_callocN(sizeof(RenderView), "fullsample renderview"); /* we accumulate in here */ - rv->rectf = MEM_mapallocN(re->rectx * re->recty * sizeof(float) * 4, "fullsample rgba"); + rv->rectf = MEM_mapallocN(re->result->rectx * re->result->recty * sizeof(float) * 4, "fullsample rgba"); BLI_addtail(rectfs, rv); } @@ -2347,6 +2347,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) composite_freestyle_renders(re1, sample); #endif BLI_rw_mutex_unlock(&re->resultmutex); + render_result_uncrop(re1); } ntreeCompositTagRender(re1->scene); /* ensure node gets exec to put buffers on stack */ } @@ -2373,17 +2374,17 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) mask = (1 << sample); mask_array(mask, filt); - for (y = 0; y < re->recty; y++) { - float *rf = rectf + 4 * y * re->rectx; - float *col = rres.rectf + 4 * y * re->rectx; + for (y = 0; y < re->result->recty; y++) { + float *rf = rectf + 4 * y * re->result->rectx; + float *col = rres.rectf + 4 * y * re->result->rectx; - for (x = 0; x < re->rectx; x++, rf += 4, col += 4) { + for (x = 0; x < re->result->rectx; x++, rf += 4, col += 4) { /* clamping to 1.0 is needed for correct AA */ CLAMP(col[0], 0.0f, 1.0f); CLAMP(col[1], 0.0f, 1.0f); CLAMP(col[2], 0.0f, 1.0f); - add_filt_fmask_coord(filt, col, rf, re->rectx, re->recty, x, y); + add_filt_fmask_coord(filt, col, rf, re->result->rectx, x, y, &filter_mask); } } @@ -2403,10 +2404,10 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) rectf = ((RenderView *)BLI_findlink(rectfs, nr))->rectf; /* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */ - for (y = 0; y < re->recty; y++) { - float *rf = rectf + 4 * y * re->rectx; + for (y = 0; y < re->result->recty; y++) { + float *rf = rectf + 4 * y * re->result->rectx; - for (x = 0; x < re->rectx; x++, rf += 4) { + for (x = 0; x < re->result->rectx; x++, rf += 4) { rf[0] = MAX2(rf[0], 0.0f); rf[1] = MAX2(rf[1], 0.0f); rf[2] = MAX2(rf[2], 0.0f); @@ -3847,6 +3848,8 @@ bool RE_ReadRenderResult(Scene *scene, Scene *scenode) success = render_result_exr_file_cache_read(re); BLI_rw_mutex_unlock(&re->resultmutex); + render_result_uncrop(re); + return success; } diff --git a/source/blender/render/intern/source/pixelblending.c b/source/blender/render/intern/source/pixelblending.c index 32fb196e1f3..fc79786e5c7 100644 --- a/source/blender/render/intern/source/pixelblending.c +++ b/source/blender/render/intern/source/pixelblending.c @@ -240,7 +240,7 @@ void mask_array(unsigned int mask, float filt[3][3]) * */ -void add_filt_fmask_coord(float filt[3][3], const float col[4], float *rowbuf, int row_w, int col_h, int x, int y) +void add_filt_fmask_coord(float filt[3][3], const float col[4], float *rowbuf, int row_stride, int x, int y, rcti *mask) { float *fpoin[3][3]; float val, r, g, b, al, lfilt[3][3]; @@ -252,9 +252,9 @@ void add_filt_fmask_coord(float filt[3][3], const float col[4], float *rowbuf, i memcpy(lfilt, filt, sizeof(lfilt)); - fpoin[0][1] = rowbuf - 4 * row_w; + fpoin[0][1] = rowbuf - 4 * row_stride; fpoin[1][1] = rowbuf; - fpoin[2][1] = rowbuf + 4 * row_w; + fpoin[2][1] = rowbuf + 4 * row_stride; fpoin[0][0] = fpoin[0][1] - 4; fpoin[1][0] = fpoin[1][1] - 4; @@ -264,7 +264,9 @@ void add_filt_fmask_coord(float filt[3][3], const float col[4], float *rowbuf, i fpoin[1][2] = fpoin[1][1] + 4; fpoin[2][2] = fpoin[2][1] + 4; - if (y == 0) { + /* limit filtering to withing a mask for border rendering, so pixels don't + * leak outside of the border */ + if (y <= mask->ymin) { fpoin[0][0] = fpoin[1][0]; fpoin[0][1] = fpoin[1][1]; fpoin[0][2] = fpoin[1][2]; @@ -273,7 +275,7 @@ void add_filt_fmask_coord(float filt[3][3], const float col[4], float *rowbuf, i lfilt[0][1] = filt[2][1]; lfilt[0][2] = filt[2][2]; } - else if (y == col_h - 1) { + else if (y >= mask->ymax - 1) { fpoin[2][0] = fpoin[1][0]; fpoin[2][1] = fpoin[1][1]; fpoin[2][2] = fpoin[1][2]; @@ -283,7 +285,7 @@ void add_filt_fmask_coord(float filt[3][3], const float col[4], float *rowbuf, i lfilt[2][2] = filt[0][2]; } - if (x == 0) { + if (x <= mask->xmin) { fpoin[2][0] = fpoin[2][1]; fpoin[1][0] = fpoin[1][1]; fpoin[0][0] = fpoin[0][1]; @@ -292,7 +294,7 @@ void add_filt_fmask_coord(float filt[3][3], const float col[4], float *rowbuf, i lfilt[1][0] = filt[1][2]; lfilt[0][0] = filt[0][2]; } - else if (x == row_w - 1) { + else if (x >= mask->xmax - 1) { fpoin[2][2] = fpoin[2][1]; fpoin[1][2] = fpoin[1][1]; fpoin[0][2] = fpoin[0][1];