diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-09-04 17:29:07 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-09-04 17:29:07 +0400 |
commit | adea12cb01e4c4f18f345dfbbf49e9e622192e4e (patch) | |
tree | b43018344c696e4d59437fabc7f17f5b9d6a8e80 /source | |
parent | 68563134d4800be4eb46aa6b598fd719cdaf2980 (diff) |
Cycles: merge of changes from tomato branch.
Regular rendering now works tiled, and supports save buffers to save memory
during render and cache render results.
Brick texture node by Thomas.
http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes/Textures#Brick_Texture
Image texture Blended Box Mapping.
http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes/Textures#Image_Texture
http://mango.blender.org/production/blended_box/
Various bug fixes by Sergey and Campbell.
* Fix for reading freed memory in some node setups.
* Fix incorrect memory read when synchronizing mesh motion.
* Fix crash appearing when direct light usage is different on different layers.
* Fix for vector pass gives wrong result in some circumstances.
* Fix for wrong resolution used for rendering Render Layer node.
* Option to cancel rendering when doing initial synchronization.
* No more texture limit when using CPU render.
* Many fixes for new tiled rendering.
Diffstat (limited to 'source')
19 files changed, 402 insertions, 101 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index c8b69898daa..438d5110666 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -546,6 +546,7 @@ struct ShadeResult; #define SH_NODE_LIGHT_FALLOFF 166 #define SH_NODE_OBJECT_INFO 167 #define SH_NODE_PARTICLE_INFO 168 +#define SH_NODE_TEX_BRICK 169 /* custom defines options for Material node */ #define SH_NODE_MAT_DIFF 1 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index d5c451799ae..ade418e409f 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2263,6 +2263,7 @@ static void registerShaderNodes(bNodeTreeType *ttype) register_node_type_sh_tex_gradient(ttype); register_node_type_sh_tex_magic(ttype); register_node_type_sh_tex_checker(ttype); + register_node_type_sh_tex_brick(ttype); } static void registerTextureNodes(bNodeTreeType *ttype) diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 8a1f0e5b611..2688c1e8594 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1324,6 +1324,10 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL); uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE); + uiItemR(layout, ptr, "projection", 0, "", ICON_NONE); + + if(RNA_enum_get(ptr, "projection") == SHD_PROJ_BOX) + uiItemR(layout, ptr, "projection_blend", 0, "Blend", ICON_NONE); /* note: image user properties used directly here, unlike compositor image node, * which redefines them in the node struct RNA to get proper updates. @@ -1359,6 +1363,19 @@ static void node_shader_buts_tex_magic(uiLayout *layout, bContext *UNUSED(C), Po uiItemR(layout, ptr, "turbulence_depth", 0, NULL, ICON_NONE); } +static void node_shader_buts_tex_brick(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiLayout *col; + + col = uiLayoutColumn(layout, TRUE); + uiItemR(col, ptr, "offset", 0, IFACE_("Offset"), ICON_NONE); + uiItemR(col, ptr, "offset_frequency", 0, IFACE_("Frequency"), ICON_NONE); + + col = uiLayoutColumn(layout, TRUE); + uiItemR(col, ptr, "squash", 0, IFACE_("Squash"), ICON_NONE); + uiItemR(col, ptr, "squash_frequency", 0, IFACE_("Frequency"), ICON_NONE); +} + static void node_shader_buts_tex_wave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiItemR(layout, ptr, "wave_type", 0, "", ICON_NONE); @@ -1443,6 +1460,9 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_TEX_MAGIC: ntype->uifunc = node_shader_buts_tex_magic; break; + case SH_NODE_TEX_BRICK: + ntype->uifunc = node_shader_buts_tex_brick; + break; case SH_NODE_TEX_WAVE: ntype->uifunc = node_shader_buts_tex_wave; break; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index d7e61d0bff3..18ad99e1cdb 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -2827,13 +2827,21 @@ static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar, int draw /* create render engine */ if (!rv3d->render_engine) { + RenderEngine *engine; + type = RE_engines_find(scene->r.engine); if (!(type->view_update && type->view_draw)) return 0; - rv3d->render_engine = RE_engine_create(type); - type->view_update(rv3d->render_engine, C); + engine = RE_engine_create(type); + + engine->tile_x = scene->r.xparts; + engine->tile_y = scene->r.yparts; + + type->view_update(engine, C); + + rv3d->render_engine = engine; } /* setup view matrices */ diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index fb248f1b016..81c3cab97d4 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -2114,6 +2114,12 @@ void node_tex_checker(vec3 co, vec4 color1, vec4 color2, float scale, out vec4 c fac = 1.0; } +void node_tex_brick(vec3 co, vec4 color1, vec4 color2, vec4 mortar, float scale, float mortar_size, float bias, float brick_width, float row_height, out vec4 color, out float fac) +{ + color = vec4(1.0); + fac = 1.0; +} + void node_tex_clouds(vec3 co, float size, out vec4 color, out float fac) { color = vec4(1.0); diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index ffb16b96b55..3f1f4933585 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -614,17 +614,27 @@ typedef struct NodeTexSky { typedef struct NodeTexImage { NodeTexBase base; ImageUser iuser; - int color_space, pad; + int color_space; + int projection; + float projection_blend; + int pad; } NodeTexImage; typedef struct NodeTexChecker { NodeTexBase base; } NodeTexChecker; +typedef struct NodeTexBrick { + NodeTexBase base; + int offset_freq, squash_freq; + float offset, squash; +} NodeTexBrick; + typedef struct NodeTexEnvironment { NodeTexBase base; ImageUser iuser; - int color_space, projection; + int color_space; + int projection; } NodeTexEnvironment; typedef struct NodeTexGradient { @@ -764,6 +774,10 @@ typedef struct NodeTrackPosData { #define SHD_PROJ_EQUIRECTANGULAR 0 #define SHD_PROJ_MIRROR_BALL 1 +/* image texture */ +#define SHD_PROJ_FLAT 0 +#define SHD_PROJ_BOX 1 + /* blur node */ #define CMP_NODE_BLUR_ASPECT_NONE 0 #define CMP_NODE_BLUR_ASPECT_Y 1 diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 2f763a6ed0e..55dda3fc315 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -1526,6 +1526,15 @@ static void def_sh_tex_image(StructRNA *srna) {0, NULL, 0, NULL, NULL} }; + static const EnumPropertyItem prop_projection_items[] = { + {SHD_PROJ_FLAT, "FLAT", 0, "Flat", + "Image is projected flat using the X and Y coordinates of the texture vector"}, + {SHD_PROJ_BOX, "BOX", 0, "Box", + "Image is projected using different components for each side of the object space bounding box"}, + {0, NULL, 0, NULL, NULL} + }; + + PropertyRNA *prop; prop = RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE); @@ -1543,6 +1552,15 @@ static void def_sh_tex_image(StructRNA *srna) RNA_def_property_ui_text(prop, "Color Space", "Image file color space"); RNA_def_property_update(prop, 0, "rna_Node_update"); + prop = RNA_def_property(srna, "projection", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_projection_items); + RNA_def_property_ui_text(prop, "Projection", "Method to project 2D image on object with a 3D texture vector"); + RNA_def_property_update(prop, 0, "rna_Node_update"); + + prop = RNA_def_property(srna, "projection_blend", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_ui_text(prop, "Projection Blend", "For box projection, amount of blend to use between sides"); + RNA_def_property_update(prop, 0, "rna_Node_update"); + prop = RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "iuser"); @@ -1588,6 +1606,43 @@ static void def_sh_tex_checker(StructRNA *srna) def_sh_tex(srna); } +static void def_sh_tex_brick(StructRNA *srna) +{ + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeTexBrick", "storage"); + def_sh_tex(srna); + + prop = RNA_def_property(srna, "offset_frequency", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "offset_freq"); + RNA_def_property_int_default(prop, 2); + RNA_def_property_range(prop, 1, 99); + RNA_def_property_ui_text(prop, "Offset Frequency", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); + + prop = RNA_def_property(srna, "squash_frequency", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "squash_freq"); + RNA_def_property_int_default(prop, 2); + RNA_def_property_range(prop, 1, 99); + RNA_def_property_ui_text(prop, "Squash Frequency", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); + + prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "offset"); + RNA_def_property_float_default(prop, 0.5f); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Offset Amount", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); + + prop = RNA_def_property(srna, "squash", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "squash"); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_range(prop, 0.0f, 99.0f); + RNA_def_property_ui_text(prop, "Squash Amount", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); + +} + static void def_sh_tex_magic(StructRNA *srna) { PropertyRNA *prop; diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index 15ad1c557a5..0baa4cc0838 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -91,6 +91,7 @@ DefNode( ShaderNode, SH_NODE_TEX_WAVE, def_sh_tex_wave, "TE DefNode( ShaderNode, SH_NODE_TEX_MUSGRAVE, def_sh_tex_musgrave, "TEX_MUSGRAVE", TexMusgrave, "Musgrave Texture", "" ) DefNode( ShaderNode, SH_NODE_TEX_VORONOI, def_sh_tex_voronoi, "TEX_VORONOI", TexVoronoi, "Voronoi Texture", "" ) DefNode( ShaderNode, SH_NODE_TEX_CHECKER, def_sh_tex_checker, "TEX_CHECKER", TexChecker, "Checker Texture", "" ) +DefNode( ShaderNode, SH_NODE_TEX_BRICK, def_sh_tex_brick, "TEX_BRICK", TexBrick, "Brick Texture", "" ) DefNode( ShaderNode, SH_NODE_TEX_COORD, 0, "TEX_COORD", TexCoord, "Texture Coordinate","" ) DefNode( CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" ) diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index d162cad72cd..a755e130bb7 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -317,6 +317,7 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_REQUIRED); prop = RNA_def_int(func, "h", 0, 0, INT_MAX, "Height", "", 0, INT_MAX); RNA_def_property_flag(prop, PROP_REQUIRED); + prop = RNA_def_string(func, "layer", "", 0, "Layer", "Single layer to get render result for"); prop = RNA_def_pointer(func, "result", "RenderResult", "Result", ""); RNA_def_function_return(func, prop); @@ -326,6 +327,7 @@ static void rna_def_render_engine(BlenderRNA *brna) func = RNA_def_function(srna, "end_result", "RE_engine_end_result"); prop = RNA_def_pointer(func, "result", "RenderResult", "Result", ""); + prop = RNA_def_boolean(func, "cancel", 0, "Cancel", "Don't merge back results"); RNA_def_property_flag(prop, PROP_REQUIRED); func = RNA_def_function(srna, "test_break", "RE_engine_test_break"); @@ -360,6 +362,19 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "camera_override"); RNA_def_property_struct_type(prop, "Object"); + prop = RNA_def_property(srna, "tile_x", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "tile_x"); + prop = RNA_def_property(srna, "tile_y", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "tile_y"); + + prop = RNA_def_property(srna, "resolution_x", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "resolution_x"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop = RNA_def_property(srna, "resolution_y", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "resolution_y"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + /* registration */ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index e1adb419a8a..08e0e7b0f93 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -180,6 +180,7 @@ set(SRC shader/nodes/node_shader_tex_voronoi.c shader/nodes/node_shader_tex_wave.c shader/nodes/node_shader_tex_checker.c + shader/nodes/node_shader_tex_brick.c shader/node_shader_tree.c shader/node_shader_util.c diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c new file mode 100644 index 00000000000..11f7fb94ae0 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c @@ -0,0 +1,90 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../node_shader_util.h" + +/* **************** OUTPUT ******************** */ + +static bNodeSocketTemplate sh_node_tex_brick_in[]= { + { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, + { SOCK_RGBA, 1, N_("Color1"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 1, N_("Color2"), 0.2f, 0.2f, 0.2f, 1.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 1, N_("Mortar"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, + { SOCK_FLOAT, 1, N_("Mortar Size"), 0.02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.125f}, + { SOCK_FLOAT, 1, N_("Bias"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Brick Width"), 0.5f, 0.0f, 0.0f, 0.0f, 0.01f, 100.0f}, + { SOCK_FLOAT, 1, N_("Row Height"), 0.25f, 0.0f, 0.0f, 0.0f, 0.01f, 100.0f}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_tex_brick_out[]= { + { SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp)) +{ + NodeTexBrick *tex = MEM_callocN(sizeof(NodeTexBrick), "NodeTexBrick"); + default_tex_mapping(&tex->base.tex_mapping); + default_color_mapping(&tex->base.color_mapping); + + tex->offset = 0.5f; + tex->squash = 1.0f; + tex->offset_freq = 2; + tex->squash_freq = 2; + + node->storage = tex; +} + +static int node_shader_gpu_tex_brick(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + if (!in[0].link) + in[0].link = GPU_attribute(CD_ORCO, ""); + + node_shader_gpu_tex_mapping(mat, node, in, out); + + return GPU_stack_link(mat, "node_tex_brick", in, out); +} + +/* node type definition */ +void register_node_type_sh_tex_brick(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, SH_NODE_TEX_BRICK, "Brick Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, sh_node_tex_brick_in, sh_node_tex_brick_out); + node_type_size(&ntype, 150, 60, 200); + node_type_init(&ntype, node_shader_init_tex_brick); + node_type_storage(&ntype, "NodeTexBrick", node_free_standard_storage, node_copy_standard_storage); + node_type_exec(&ntype, NULL); + node_type_gpu(&ntype, node_shader_gpu_tex_brick); + + nodeRegisterType(ttype, &ntype); +} diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index 5afdb2a29ce..2376aeca55e 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -86,9 +86,14 @@ typedef struct RenderEngine { int flag; struct Object *camera_override; + int tile_x; + int tile_y; + struct Render *re; ListBase fullresult; char *text; + + int resolution_x, resolution_y; } RenderEngine; RenderEngine *RE_engine_create(RenderEngineType *type); @@ -97,9 +102,9 @@ void RE_engine_free(RenderEngine *engine); void RE_layer_load_from_file(struct RenderLayer *layer, struct ReportList *reports, const char *filename, int x, int y); void RE_result_load_from_file(struct RenderResult *result, struct ReportList *reports, const char *filename); -struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h); +struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername); void RE_engine_update_result(RenderEngine *engine, struct RenderResult *result); -void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result); +void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int cancel); int RE_engine_test_break(RenderEngine *engine); void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info); diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index d474dc14df8..b43824d6d5e 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -92,6 +92,9 @@ typedef struct RenderLayer { float *acolrect; /* 4 float, optional transparent buffer, needs storage for display updates */ float *scolrect; /* 4 float, optional strand buffer, needs storage for display updates */ int rectx, recty; + + /* optional saved endresult on disk */ + void *exrhandle; ListBase passes; @@ -124,7 +127,7 @@ typedef struct RenderResult { volatile RenderLayer *renlay; /* optional saved endresult on disk */ - void *exrhandle; + int do_exr_tile; /* for render results in Image, verify validity for sequences */ int framenr; diff --git a/source/blender/render/intern/include/initrender.h b/source/blender/render/intern/include/initrender.h index 7917fd66cfa..43ab9552194 100644 --- a/source/blender/render/intern/include/initrender.h +++ b/source/blender/render/intern/include/initrender.h @@ -40,7 +40,7 @@ struct Object; void free_sample_tables(Render *re); void make_sample_tables(Render *re); -void initparts(Render *re); +void initparts(Render *re, int do_crop); void freeparts(Render *re); diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h index 3d73ee1e912..303d4094f8e 100644 --- a/source/blender/render/intern/include/render_result.h +++ b/source/blender/render/intern/include/render_result.h @@ -37,6 +37,8 @@ #define RR_USE_MEM 0 #define RR_USE_EXR 1 +#define RR_ALL_LAYERS NULL + struct ImBuf; struct ListBase; struct Render; @@ -49,7 +51,7 @@ struct rcti; /* New */ struct RenderResult *render_result_new(struct Render *re, - struct rcti *partrct, int crop, int savebuffers); + struct rcti *partrct, int crop, int savebuffers, const char *layername); struct RenderResult *render_result_new_full_sample(struct Render *re, struct ListBase *lb, struct rcti *partrct, int crop, int savebuffers); @@ -76,9 +78,9 @@ void render_result_exr_file_end(struct Render *re); void render_result_exr_file_merge(struct RenderResult *rr, struct RenderResult *rrpart); -void render_result_exr_file_path(struct Scene *scene, int sample, char *filepath); +void render_result_exr_file_path(struct Scene *scene, const char *layname, int sample, char *filepath); int render_result_exr_file_read(struct Render *re, int sample); -int render_result_exr_file_read_path(struct RenderResult *rr, const char *filepath); +int render_result_exr_file_read_path(struct RenderResult *rr, struct RenderLayer *rl_single, const char *filepath); /* Combined Pixel Rect */ diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 487271ea1f7..57993874c7a 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -55,6 +55,7 @@ #include "RE_engine.h" #include "RE_pipeline.h" +#include "initrender.h" #include "render_types.h" #include "render_result.h" @@ -149,7 +150,7 @@ void RE_engine_free(RenderEngine *engine) /* Render Results */ -RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h) +RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername) { Render *re = engine->re; RenderResult *result; @@ -172,7 +173,9 @@ RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, disprect.ymin = y; disprect.ymax = y + h; - result = render_result_new(re, &disprect, 0, RR_USE_MEM); + result = render_result_new(re, &disprect, 0, RR_USE_MEM, layername); + + /* todo: make this thread safe */ /* can be NULL if we CLAMP the width or height to 0 */ if (result) { @@ -197,25 +200,41 @@ void RE_engine_update_result(RenderEngine *engine, RenderResult *result) } } -void RE_engine_end_result(RenderEngine *engine, RenderResult *result) +void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel) { Render *re = engine->re; + RenderPart *pa; if (!result) return; /* merge. on break, don't merge in result for preview renders, looks nicer */ - if (!(re->test_break(re->tbh) && (re->r.scemode & R_PREVIEWBUTS))) - render_result_merge(re->result, result); + if (!cancel) { + /* for exr tile render, detect tiles that are done */ + for (pa = re->parts.first; pa; pa = pa->next) { + if (result->tilerect.xmin == pa->disprect.xmin && + result->tilerect.ymin == pa->disprect.ymin && + result->tilerect.xmax == pa->disprect.xmax && + result->tilerect.ymax == pa->disprect.ymax) { + pa->ready = 1; + } + } - /* draw */ - if (!re->test_break(re->tbh)) { - result->renlay = result->layers.first; /* weak, draws first layer always */ - re->display_draw(re->ddh, result, NULL); + if (re->result->do_exr_tile) + render_result_exr_file_merge(re->result, result); + else if (!(re->test_break(re->tbh) && (re->r.scemode & R_PREVIEWBUTS))) + render_result_merge(re->result, result); + + /* draw */ + if (!re->test_break(re->tbh)) { + result->renlay = result->layers.first; /* weak, draws first layer always */ + re->display_draw(re->ddh, result, NULL); + } } /* free */ - render_result_free_list(&engine->fullresult, result); + BLI_remlink(&engine->fullresult, result); + render_result_free(result); } /* Cancel */ @@ -294,12 +313,16 @@ int RE_engine_render(Render *re, int do_all) /* create render result */ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if (re->result == NULL || !(re->r.scemode & R_PREVIEWBUTS)) { + int savebuffers; + if (re->result) render_result_free(re->result); - re->result = render_result_new(re, &re->disprect, 0, 0); + + savebuffers = (re->r.scemode & R_EXR_TILE_FILE) ? RR_USE_EXR : RR_USE_MEM; + re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS); } BLI_rw_mutex_unlock(&re->resultmutex); - + if (re->result == NULL) return 1; @@ -318,14 +341,35 @@ int RE_engine_render(Render *re, int do_all) engine->flag |= RE_ENGINE_PREVIEW; engine->camera_override = re->camera_override; + engine->resolution_x = re->winx; + engine->resolution_y = re->winy; + if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_PREVIEWBUTS)) == 0) BKE_scene_update_for_newframe(re->main, re->scene, re->lay); + initparts(re, FALSE); + engine->tile_x = re->partx; + engine->tile_y = re->party; + + if (re->result->do_exr_tile) + render_result_exr_file_begin(re); + if (type->update) type->update(engine, re->main, re->scene); + if (type->render) type->render(engine, re->scene); + if (re->result->do_exr_tile) { + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + render_result_exr_file_end(re); + BLI_rw_mutex_unlock(&re->resultmutex); + } + + engine->tile_x = 0; + engine->tile_y = 0; + freeparts(re); + render_result_free_list(&engine->fullresult, engine->fullresult.first); RE_engine_free(engine); diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c index 7efdba77943..66f230a40f5 100644 --- a/source/blender/render/intern/source/initrender.c +++ b/source/blender/render/intern/source/initrender.c @@ -537,7 +537,7 @@ void freeparts(Render *re) BLI_freelistN(&re->parts); } -void initparts(Render *re) +void initparts(Render *re, int do_crop) { int nr, xd, yd, partx, party, xparts, yparts; int xminb, xmaxb, yminb, ymaxb; @@ -618,7 +618,7 @@ void initparts(Render *re) RenderPart *pa = MEM_callocN(sizeof(RenderPart), "new part"); /* Non-box filters need 2 pixels extra to work */ - if ((re->r.filtertype || (re->r.mode & R_EDGE))) { + if (do_crop && (re->r.filtertype || (re->r.mode & R_EDGE))) { pa->crop = 2; disprect.xmin -= pa->crop; disprect.ymin -= pa->crop; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 48000ff258b..3e34b9d86d3 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -640,7 +640,7 @@ static void *do_part_thread(void *pa_v) if (!R.sss_points && (R.r.scemode & R_FULL_SAMPLE)) pa->result = render_result_new_full_sample(&R, &pa->fullresult, &pa->disprect, pa->crop, RR_USE_MEM); else - pa->result = render_result_new(&R, &pa->disprect, pa->crop, RR_USE_MEM); + pa->result = render_result_new(&R, &pa->disprect, pa->crop, RR_USE_MEM, RR_ALL_LAYERS); if (R.sss_points) zbufshade_sss_tile(pa); @@ -650,7 +650,7 @@ static void *do_part_thread(void *pa_v) zbufshade_tile(pa); /* merge too on break! */ - if (R.result->exrhandle) { + if (R.result->do_exr_tile) { render_result_exr_file_merge(R.result, pa->result); } else if (render_display_draw_enabled(&R)) { @@ -794,12 +794,12 @@ static void threaded_tile_processor(Render *re) render_result_free(re->result); if (re->sss_points && render_display_draw_enabled(re)) - re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM); + re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS); else if (re->r.scemode & R_FULL_SAMPLE) re->result = render_result_new_full_sample(re, &re->fullresult, &re->disprect, 0, RR_USE_EXR); else re->result = render_result_new(re, &re->disprect, 0, - (re->r.scemode & R_EXR_TILE_FILE) ? RR_USE_EXR : RR_USE_MEM); + (re->r.scemode & R_EXR_TILE_FILE) ? RR_USE_EXR : RR_USE_MEM, RR_ALL_LAYERS); } BLI_rw_mutex_unlock(&re->resultmutex); @@ -809,9 +809,9 @@ static void threaded_tile_processor(Render *re) /* warning; no return here without closing exr file */ - initparts(re); + initparts(re, TRUE); - if (re->result->exrhandle) + if (re->result->do_exr_tile) render_result_exr_file_begin(re); BLI_init_threads(&threads, do_part_thread, re->r.threads); @@ -891,7 +891,7 @@ static void threaded_tile_processor(Render *re) } - if (re->result->exrhandle) { + if (re->result->do_exr_tile) { BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); render_result_exr_file_end(re); BLI_rw_mutex_unlock(&re->resultmutex); @@ -1044,7 +1044,7 @@ static void do_render_blur_3d(Render *re) int blur = re->r.mblur_samples; /* create accumulation render result */ - rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM); + rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS); /* do the blur steps */ while (blur--) { @@ -1169,7 +1169,7 @@ static void do_render_fields_3d(Render *re) re->disprect.ymax *= 2; BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM); + re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS); if (rr2) { if (re->r.mode & R_ODDFIELD) @@ -1232,7 +1232,7 @@ static void do_render_fields_blur_3d(Render *re) re->rectx = re->winx; re->recty = re->winy; - rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM); + rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS); render_result_merge(rres, re->result); render_result_free(re->result); @@ -1552,7 +1552,7 @@ static void do_render_composite_fields_blur_3d(Render *re) BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); render_result_free(re->result); - re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM); + re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS); BLI_rw_mutex_unlock(&re->resultmutex); @@ -1847,7 +1847,7 @@ int RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *r if (scene->r.scemode & (R_EXR_TILE_FILE | R_FULL_SAMPLE)) { char str[FILE_MAX]; - render_result_exr_file_path(scene, 0, str); + render_result_exr_file_path(scene, "", 0, str); if (BLI_file_is_writable(str) == 0) { BKE_report(reports, RPT_ERROR, "Can not save render buffers, check the temp default path"); @@ -1931,7 +1931,7 @@ static void validate_render_settings(Render *re) if (RE_engine_is_external(re)) { /* not supported yet */ - re->r.scemode &= ~(R_EXR_TILE_FILE | R_FULL_SAMPLE); + re->r.scemode &= ~(R_FULL_SAMPLE); re->r.mode &= ~(R_FIELDS | R_MBLUR); } } @@ -2421,7 +2421,7 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char void RE_result_load_from_file(RenderResult *result, ReportList *reports, const char *filename) { - if (!render_result_exr_file_read_path(result, filename)) { + if (!render_result_exr_file_read_path(result, NULL, filename)) { BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'\n", filename); return; } diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index d31f69fe825..4b0e46c9054 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -384,10 +384,10 @@ static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channel rpass->recty = rl->recty; BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name)); - if (rr->exrhandle) { + if (rl->exrhandle) { int a; for (a = 0; a < channels; a++) - IMB_exr_add_channel(rr->exrhandle, rl->name, get_pass_name(passtype, a), 0, 0, NULL); + IMB_exr_add_channel(rl->exrhandle, rl->name, get_pass_name(passtype, a), 0, 0, NULL); } else { float *rect; @@ -413,7 +413,7 @@ static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channel /* will read info from Render *re to define layers */ /* called in threads */ /* re->winx,winy is coordinate space of entire image, partrct the part within */ -RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuffers) +RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuffers, const char *layername) { RenderResult *rr; RenderLayer *rl; @@ -435,17 +435,21 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf /* tilerect is relative coordinates within render disprect. do not subtract crop yet */ rr->tilerect.xmin = partrct->xmin - re->disprect.xmin; - rr->tilerect.xmax = partrct->xmax - re->disprect.xmax; + rr->tilerect.xmax = partrct->xmax - re->disprect.xmin; rr->tilerect.ymin = partrct->ymin - re->disprect.ymin; - rr->tilerect.ymax = partrct->ymax - re->disprect.ymax; + rr->tilerect.ymax = partrct->ymax - re->disprect.ymin; if (savebuffers) { - rr->exrhandle = IMB_exr_get_handle(); + rr->do_exr_tile = TRUE; } - + /* check renderdata for amount of layers */ for (nr = 0, srl = re->r.layers.first; srl; srl = srl->next, nr++) { - + + if (layername && layername[0]) + if (strcmp(srl->name, layername) != 0) + continue; + if ((re->r.scemode & R_SINGLE_LAYER) && nr != re->r.actlay) continue; if (srl->layflag & SCE_LAY_DISABLE) @@ -466,11 +470,13 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf rl->rectx = rectx; rl->recty = recty; - if (rr->exrhandle) { - IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R", 0, 0, NULL); - IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G", 0, 0, NULL); - IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B", 0, 0, NULL); - IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A", 0, 0, NULL); + if (rr->do_exr_tile) { + rl->exrhandle = IMB_exr_get_handle(); + + IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.R", 0, 0, NULL); + IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.G", 0, 0, NULL); + IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.B", 0, 0, NULL); + IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.A", 0, 0, NULL); } else rl->rectf = MEM_mapallocN(rectx * recty * sizeof(float) * 4, "Combined rgba"); @@ -532,7 +538,7 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf } /* sss, previewrender and envmap don't do layers, so we make a default one */ - if (rr->layers.first == NULL) { + if (rr->layers.first == NULL && !(layername && layername[0])) { rl = MEM_callocN(sizeof(RenderLayer), "new render layer"); BLI_addtail(&rr->layers, rl); @@ -540,11 +546,13 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf rl->recty = recty; /* duplicate code... */ - if (rr->exrhandle) { - IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R", 0, 0, NULL); - IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G", 0, 0, NULL); - IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B", 0, 0, NULL); - IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A", 0, 0, NULL); + if (rr->do_exr_tile) { + rl->exrhandle = IMB_exr_get_handle(); + + IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.R", 0, 0, NULL); + IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.G", 0, 0, NULL); + IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.B", 0, 0, NULL); + IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.A", 0, 0, NULL); } else rl->rectf = MEM_mapallocN(rectx * recty * sizeof(float) * 4, "Combined rgba"); @@ -570,10 +578,10 @@ RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *part int a; if (re->osa == 0) - return render_result_new(re, partrct, crop, savebuffers); + return render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS); for (a = 0; a < re->osa; a++) { - RenderResult *rr = render_result_new(re, partrct, crop, savebuffers); + RenderResult *rr = render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS); BLI_addtail(lb, rr); rr->sample_nr = a; } @@ -682,15 +690,18 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart) RenderLayer *rl, *rlp; RenderPass *rpass, *rpassp; - for (rl = rr->layers.first, rlp = rrpart->layers.first; rl && rlp; rl = rl->next, rlp = rlp->next) { - - /* combined */ - if (rl->rectf && rlp->rectf) - do_merge_tile(rr, rrpart, rl->rectf, rlp->rectf, 4); - - /* passes are allocated in sync */ - for (rpass = rl->passes.first, rpassp = rlp->passes.first; rpass && rpassp; rpass = rpass->next, rpassp = rpassp->next) { - do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels); + for (rl = rr->layers.first; rl; rl = rl->next) { + for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) { + if (strcmp(rlp->name, rl->name) == 0) { + /* combined */ + if (rl->rectf && rlp->rectf) + do_merge_tile(rr, rrpart, rl->rectf, rlp->rectf, 4); + + /* passes are allocated in sync */ + for (rpass = rl->passes.first, rpassp = rlp->passes.first; rpass && rpassp; rpass = rpass->next, rpassp = rpassp->next) { + do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels); + } + } } } } @@ -827,13 +838,16 @@ void render_result_single_layer_end(Render *re) static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart) { - RenderLayer *rlp; + RenderLayer *rlp, *rl; RenderPass *rpassp; int offs, partx, party; BLI_lock_thread(LOCK_IMAGE); for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) { + for (rl = rr->layers.first; rl; rl = rl->next) + if (strcmp(rl->name, rlp->name) == 0) + break; if (rrpart->crop) { /* filters add pixel extra */ offs = (rrpart->crop + rrpart->crop * rrpart->rectx); @@ -846,7 +860,7 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart) if (rlp->rectf) { int a, xstride = 4; for (a = 0; a < xstride; a++) - IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(SCE_PASS_COMBINED, a), + IMB_exr_set_channel(rl->exrhandle, rlp->name, get_pass_name(SCE_PASS_COMBINED, a), xstride, xstride * rrpart->rectx, rlp->rectf + a + xstride * offs); } @@ -854,7 +868,7 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart) for (rpassp = rlp->passes.first; rpassp; rpassp = rpassp->next) { int a, xstride = rpassp->channels; for (a = 0; a < xstride; a++) - IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a), + IMB_exr_set_channel(rl->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a), xstride, xstride * rrpart->rectx, rpassp->rect + a + xstride * offs); } @@ -862,7 +876,14 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart) party = rrpart->tilerect.ymin + rrpart->crop; partx = rrpart->tilerect.xmin + rrpart->crop; - IMB_exrtile_write_channels(rr->exrhandle, partx, party, 0); + + for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) { + for (rl = rr->layers.first; rl; rl = rl->next) + if (strcmp(rl->name, rlp->name) == 0) + break; + + IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0); + } BLI_unlock_thread(LOCK_IMAGE); } @@ -871,15 +892,18 @@ static void save_empty_result_tiles(Render *re) { RenderPart *pa; RenderResult *rr; + RenderLayer *rl; for (rr = re->result; rr; rr = rr->next) { - IMB_exrtile_clear_channels(rr->exrhandle); + for (rl = rr->layers.first; rl; rl = rl->next) { + IMB_exrtile_clear_channels(rl->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(rr->exrhandle, partx, party, 0); + 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(rl->exrhandle, partx, party, 0); + } } } } @@ -889,13 +913,15 @@ static void save_empty_result_tiles(Render *re) void render_result_exr_file_begin(Render *re) { RenderResult *rr; + RenderLayer *rl; char str[FILE_MAX]; - + for (rr = re->result; rr; rr = rr->next) { - render_result_exr_file_path(re->scene, rr->sample_nr, str); - - printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str); - IMB_exrtile_begin_write(rr->exrhandle, str, 0, rr->rectx, rr->recty, re->partx, re->party); + for (rl = rr->layers.first; rl; rl = rl->next) { + render_result_exr_file_path(re->scene, rl->name, rr->sample_nr, str); + printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str); + IMB_exrtile_begin_write(rl->exrhandle, str, 0, rr->rectx, rr->recty, re->partx, re->party); + } } } @@ -903,12 +929,17 @@ void render_result_exr_file_begin(Render *re) void render_result_exr_file_end(Render *re) { RenderResult *rr; + RenderLayer *rl; save_empty_result_tiles(re); for (rr = re->result; rr; rr = rr->next) { - IMB_exr_close(rr->exrhandle); - rr->exrhandle = NULL; + for (rl = rr->layers.first; rl; rl = rl->next) { + IMB_exr_close(rl->exrhandle); + rl->exrhandle = NULL; + } + + rr->do_exr_tile = FALSE; } render_result_free_list(&re->fullresult, re->result); @@ -925,17 +956,17 @@ void render_result_exr_file_merge(RenderResult *rr, RenderResult *rrpart) } /* path to temporary exr file */ -void render_result_exr_file_path(Scene *scene, int sample, char *filepath) +void render_result_exr_file_path(Scene *scene, const char *layname, int sample, char *filepath) { - char di[FILE_MAX], name[FILE_MAXFILE + MAX_ID_NAME + 100], fi[FILE_MAXFILE]; + char di[FILE_MAX], name[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100], fi[FILE_MAXFILE]; BLI_strncpy(di, G.main->name, FILE_MAX); BLI_splitdirstring(di, fi); if (sample == 0) - BLI_snprintf(name, sizeof(name), "%s_%s.exr", fi, scene->id.name + 2); + BLI_snprintf(name, sizeof(name), "%s_%s_%s.exr", fi, scene->id.name + 2, layname); else - BLI_snprintf(name, sizeof(name), "%s_%s%d.exr", fi, scene->id.name + 2, sample); + BLI_snprintf(name, sizeof(name), "%s_%s_%s%d.exr", fi, scene->id.name + 2, layname, sample); BLI_make_file_string("/", filepath, BLI_temporary_dir(), name); } @@ -943,29 +974,30 @@ void render_result_exr_file_path(Scene *scene, int sample, char *filepath) /* only for temp buffer files, makes exact copy of render result */ int render_result_exr_file_read(Render *re, int sample) { + RenderLayer *rl; char str[FILE_MAX]; - int success; + int success = TRUE; RE_FreeRenderResult(re->result); - re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM); + re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS); - render_result_exr_file_path(re->scene, sample, str); - printf("read exr tmp file: %s\n", str); + for (rl = re->result->layers.first; rl; rl = rl->next) { - if (render_result_exr_file_read_path(re->result, str)) { - success = TRUE; - } - else { - printf("cannot read: %s\n", str); - success = FALSE; + render_result_exr_file_path(re->scene, rl->name, sample, str); + printf("read exr tmp file: %s\n", str); + if (!render_result_exr_file_read_path(re->result, rl, str)) { + printf("cannot read: %s\n", str); + success = FALSE; + + } } return success; } /* called for reading temp files, and for external engines */ -int render_result_exr_file_read_path(RenderResult *rr, const char *filepath) +int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, const char *filepath) { RenderLayer *rl; RenderPass *rpass; @@ -988,6 +1020,9 @@ int render_result_exr_file_read_path(RenderResult *rr, const char *filepath) } for (rl = rr->layers.first; rl; rl = rl->next) { + if (rl_single && rl_single != rl) + continue; + /* combined */ if (rl->rectf) { int a, xstride = 4; |