diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2017-11-08 02:20:59 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2017-11-08 02:20:59 +0300 |
commit | 7b1d7074817dac9d0f088e8e7e5b336bae662c36 (patch) | |
tree | 4ebd67459d2fc160d3a6c76a2509cefc68f4e89c /source | |
parent | 1b18e158025a488e1ba2446ad93c2eb563c11611 (diff) | |
parent | a0478ebe379c8384376586e2880ebc813a6afef7 (diff) |
Merge branch 'master' into blender2.8
Diffstat (limited to 'source')
20 files changed, 448 insertions, 673 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 20516d3dd5e..7a770006e98 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -798,6 +798,7 @@ struct ShadeResult; #define SH_NODE_TEX_POINTDENSITY 192 #define SH_NODE_BSDF_PRINCIPLED 193 #define SH_NODE_EEVEE_SPECULAR 195 +#define SH_NODE_BEVEL 197 /* custom defines options for Material node */ #define SH_NODE_MAT_DIFF 1 diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 78b0eaa84ba..59fadffe22a 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2869,7 +2869,7 @@ RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser) bool is_stereo = (iuser->flag & IMA_SHOW_STEREO) && RE_RenderResult_is_stereo(rr); rv_index = is_stereo ? iuser->multiview_eye : iuser->view; - if (RE_HasFakeLayer(rr)) rl_index += 1; + if (RE_HasCombinedLayer(rr)) rl_index += 1; for (rl = rr->layers.first; rl; rl = rl->next, rl_index++) { if (iuser->layer == rl_index) { @@ -2925,7 +2925,8 @@ bool BKE_image_is_multilayer(Image *ima) bool BKE_image_is_multiview(Image *ima) { - return (BLI_listbase_count_ex(&ima->views, 2) > 1); + ImageView *view = ima->views.first; + return (view && (view->next || view->name[0])); } bool BKE_image_is_stereo(Image *ima) @@ -3031,51 +3032,6 @@ void BKE_image_backup_render(Scene *scene, Image *ima, bool free_current_slot) ima->last_render_slot = slot; } -/**************************** multiview save openexr *********************************/ -#ifdef WITH_OPENEXR -static const char *image_get_view_cb(void *base, const int view_id) -{ - Image *ima = base; - ImageView *iv = BLI_findlink(&ima->views, view_id); - return iv ? iv->name : ""; -} -#endif /* WITH_OPENEXR */ - -#ifdef WITH_OPENEXR -static ImBuf *image_get_buffer_cb(void *base, const int view_id) -{ - Image *ima = base; - ImageUser iuser = {0}; - - iuser.view = view_id; - iuser.ok = 1; - - BKE_image_multiview_index(ima, &iuser); - - return image_acquire_ibuf(ima, &iuser, NULL); -} -#endif /* WITH_OPENEXR */ - -bool BKE_image_save_openexr_multiview(Image *ima, ImBuf *ibuf, const char *filepath, const int flags) -{ -#ifdef WITH_OPENEXR - char name[FILE_MAX]; - bool ok; - - BLI_strncpy(name, filepath, sizeof(name)); - BLI_path_abs(name, G.main->name); - - ibuf->userdata = ima; - ok = IMB_exr_multiview_save(ibuf, name, flags, BLI_listbase_count(&ima->views), image_get_view_cb, image_get_buffer_cb); - ibuf->userdata = NULL; - - return ok; -#else - UNUSED_VARS(ima, ibuf, filepath, flags); - return false; -#endif -} - /**************************** multiview load openexr *********************************/ static void image_add_view(Image *ima, const char *viewname, const char *filepath) @@ -3108,51 +3064,6 @@ static void image_add_view(Image *ima, const char *viewname, const char *filepat } } -#ifdef WITH_OPENEXR -static void image_add_view_cb(void *base, const char *str) -{ - Image *ima = base; - image_add_view(ima, str, ima->name); -} - -static void image_add_buffer_cb(void *base, const char *str, ImBuf *ibuf, const int frame) -{ - Image *ima = base; - int id; - bool predivide = (ima->alpha_mode == IMA_ALPHA_PREMUL); - const char *colorspace = ima->colorspace_settings.name; - const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); - - if (ibuf == NULL) - return; - - id = BLI_findstringindex(&ima->views, str, offsetof(ImageView, name)); - - if (id == -1) - return; - - if (ibuf->channels >= 3) - IMB_colormanagement_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - colorspace, to_colorspace, predivide); - - image_assign_ibuf(ima, ibuf, id, frame); - IMB_freeImBuf(ibuf); -} -#endif /* WITH_OPENEXR */ - -/* after imbuf load, openexr type can return with a exrhandle open */ -/* in that case we have to build a render-result */ -#ifdef WITH_OPENEXR -static void image_create_multiview(Image *ima, ImBuf *ibuf, const int frame) -{ - BKE_image_free_views(ima); - - IMB_exr_multiview_convert(ibuf->userdata, ima, image_add_view_cb, image_add_buffer_cb, frame); - - IMB_exr_close(ibuf->userdata); -} -#endif /* WITH_OPENEXR */ - /* after imbuf load, openexr type can return with a exrhandle open */ /* in that case we have to build a render-result */ #ifdef WITH_OPENEXR @@ -3264,16 +3175,10 @@ static ImBuf *load_sequence_single(Image *ima, ImageUser *iuser, int frame, cons if (ibuf) { #ifdef WITH_OPENEXR - /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */ if (ibuf->ftype == IMB_FTYPE_OPENEXR && ibuf->userdata) { - /* handle singlelayer multiview case assign ibuf based on available views */ - if (IMB_exr_has_singlelayer_multiview(ibuf->userdata)) { - image_create_multiview(ima, ibuf, frame); - IMB_freeImBuf(ibuf); - ibuf = NULL; - } - else if (IMB_exr_has_multilayer(ibuf->userdata)) { - /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */ + /* Handle multilayer and multiview cases, don't assign ibuf here. + * will be set layer in BKE_image_acquire_ibuf from ima->rr. */ + if (IMB_exr_has_multilayer(ibuf->userdata)) { image_create_multilayer(ima, ibuf, frame); ima->type = IMA_TYPE_MULTILAYER; IMB_freeImBuf(ibuf); @@ -3562,14 +3467,9 @@ static ImBuf *load_image_single( if (ibuf) { #ifdef WITH_OPENEXR if (ibuf->ftype == IMB_FTYPE_OPENEXR && ibuf->userdata) { - if (IMB_exr_has_singlelayer_multiview(ibuf->userdata)) { - /* handle singlelayer multiview case assign ibuf based on available views */ - image_create_multiview(ima, ibuf, cfra); - IMB_freeImBuf(ibuf); - ibuf = NULL; - } - else if (IMB_exr_has_multilayer(ibuf->userdata)) { - /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */ + /* Handle multilayer and multiview cases, don't assign ibuf here. + * will be set layer in BKE_image_acquire_ibuf from ima->rr. */ + if (IMB_exr_has_multilayer(ibuf->userdata)) { image_create_multilayer(ima, ibuf, cfra); ima->type = IMA_TYPE_MULTILAYER; IMB_freeImBuf(ibuf); @@ -4409,7 +4309,7 @@ void BKE_image_update_frame(const Main *bmain, int cfra) void BKE_image_user_file_path(ImageUser *iuser, Image *ima, char *filepath) { - if (BKE_image_is_multiview(ima) && (ima->rr == NULL)) { + if (BKE_image_is_multiview(ima)) { ImageView *iv = BLI_findlink(&ima->views, iuser->view); if (iv->filepath[0]) BLI_strncpy(filepath, iv->filepath, FILE_MAX); diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index a81b0b75be6..b76fd49fc9c 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -3564,6 +3564,7 @@ static void registerShaderNodes(void) register_node_type_sh_hue_sat(); register_node_type_sh_attribute(); + register_node_type_sh_bevel(); register_node_type_sh_geometry(); register_node_type_sh_light_path(); register_node_type_sh_light_falloff(); diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 8037c2deb5b..d2897c7264b 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -403,16 +403,6 @@ final: BKE_image_release_renderresult(scene, image); } -static const char *ui_imageuser_pass_fake_name(RenderLayer *rl) -{ - if (rl == NULL) { - return IFACE_("Combined"); - } - else { - return NULL; - } -} - static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt) { struct ImageUI_Data *rnd_data = rnd_pt; @@ -424,9 +414,7 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void * Scene *scene = iuser->scene; RenderResult *rr; RenderLayer *rl; - RenderPass rpass_fake = {NULL}; RenderPass *rpass; - const char *fake_name; int nr; /* may have been freed since drawing */ @@ -445,13 +433,7 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void * uiItemS(layout); - nr = 0; - fake_name = ui_imageuser_pass_fake_name(rl); - - if (fake_name) { - BLI_strncpy(rpass_fake.name, fake_name, sizeof(rpass_fake.name)); - nr += 1; - } + nr = (rl == NULL)? 1: 0; ListBase added_passes; BLI_listbase_clear(&added_passes); @@ -471,11 +453,6 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void * BLI_freelistN(&added_passes); - if (fake_name) { - uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass_fake.name), 0, 0, - UI_UNIT_X * 5, UI_UNIT_X, &iuser->pass, 0.0f, 0.0, 0, -1, ""); - } - BKE_image_release_renderresult(scene, image); } @@ -571,7 +548,7 @@ static bool ui_imageuser_layer_menu_step(bContext *C, int direction, void *rnd_p else if (direction == 1) { int tot = BLI_listbase_count(&rr->layers); - if (RE_HasFakeLayer(rr)) + if (RE_HasCombinedLayer(rr)) tot++; /* fake compo/sequencer layer */ if (iuser->layer < tot - 1) { @@ -611,7 +588,7 @@ static bool ui_imageuser_pass_menu_step(bContext *C, int direction, void *rnd_pt return false; } - if (RE_HasFakeLayer(rr)) { + if (RE_HasCombinedLayer(rr)) { layer -= 1; } @@ -770,18 +747,19 @@ static void uiblock_layer_pass_buttons( } /* pass */ - fake_name = ui_imageuser_pass_fake_name(rl); - rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass - (fake_name ? 1 : 0)) : NULL); + rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass) : NULL); - display_name = rpass ? rpass->name : (fake_name ? fake_name : ""); - rnd_pt = ui_imageuser_data_copy(&rnd_pt_local); - but = uiDefMenuBut( - block, ui_imageuser_pass_menu, rnd_pt, IFACE_(display_name), - 0, 0, wmenu3, UI_UNIT_Y, TIP_("Select Pass")); - UI_but_func_menu_step_set(but, ui_imageuser_pass_menu_step); - UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr); - UI_but_type_set_menu_from_pulldown(but); - rnd_pt = NULL; + if (rpass && RE_passes_have_name(rl)) { + display_name = rpass->name; + rnd_pt = ui_imageuser_data_copy(&rnd_pt_local); + but = uiDefMenuBut( + block, ui_imageuser_pass_menu, rnd_pt, IFACE_(display_name), + 0, 0, wmenu3, UI_UNIT_Y, TIP_("Select Pass")); + UI_but_func_menu_step_set(but, ui_imageuser_pass_menu_step); + UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr); + UI_but_type_set_menu_from_pulldown(but); + rnd_pt = NULL; + } /* view */ if (BLI_listbase_count_ex(&rr->views, 2) > 1 && @@ -1134,7 +1112,7 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man uiItemR(row, imfptr, "use_zbuffer", 0, NULL, ICON_NONE); } - if (is_render_out && (imf->imtype == R_IMF_IMTYPE_OPENEXR)) { + if (is_render_out && ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) { show_preview = true; uiItemR(row, imfptr, "use_preview", 0, NULL, ICON_NONE); } diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index dbefcf3d297..ccbc8330810 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1830,9 +1830,6 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI const bool save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") && RNA_boolean_get(op->ptr, "save_as_render")); ImageFormatData *imf = &simopts->im_format; - const bool is_multilayer = imf->imtype == R_IMF_IMTYPE_MULTILAYER; - bool is_mono; - /* old global to ensure a 2nd save goes to same dir */ BLI_strncpy(G.ima, simopts->filepath, sizeof(G.ima)); @@ -1859,7 +1856,8 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI /* we need renderresult for exr and rendered multiview */ scene = CTX_data_scene(C); rr = BKE_image_acquire_renderresult(scene, ima); - is_mono = rr ? BLI_listbase_count_ex(&rr->views, 2) < 2 : BLI_listbase_count_ex(&ima->views, 2) < 2; + bool is_mono = rr ? BLI_listbase_count_ex(&rr->views, 2) < 2 : BLI_listbase_count_ex(&ima->views, 2) < 2; + bool is_exr_rr = rr && ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER); /* error handling */ if (!rr) { @@ -1889,28 +1887,23 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI } /* fancy multiview OpenEXR */ - if ((imf->imtype == R_IMF_IMTYPE_MULTILAYER) && (imf->views_format == R_IMF_VIEWS_MULTIVIEW)) { - ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, true, NULL); + if (imf->views_format == R_IMF_VIEWS_MULTIVIEW && is_exr_rr) { + /* save render result */ + ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, NULL, sima->iuser.layer); save_image_post(op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath); ED_space_image_release_buffer(sima, ibuf, lock); } - else if ((imf->imtype == R_IMF_IMTYPE_OPENEXR) && (imf->views_format == R_IMF_VIEWS_MULTIVIEW)) { - /* treat special Openexr case separetely (this is the singlelayer multiview OpenEXR */ - BKE_imbuf_write_prepare(ibuf, imf); - ok = BKE_image_save_openexr_multiview(ima, ibuf, simopts->filepath, (IB_rect | IB_zbuf | IB_zbuffloat | IB_multiview)); - ED_space_image_release_buffer(sima, ibuf, lock); - } /* regular mono pipeline */ else if (is_mono) { - if (is_multilayer) { - ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, false, NULL); + if (is_exr_rr) { + ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, NULL, -1); } else { colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf); ok = BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, imf, save_copy); save_imbuf_post(ibuf, colormanaged_ibuf); } - save_image_post(op, ibuf, ima, ok, (is_multilayer ? true : save_copy), relbase, relative, do_newpath, simopts->filepath); + save_image_post(op, ibuf, ima, ok, (is_exr_rr ? true : save_copy), relbase, relative, do_newpath, simopts->filepath); ED_space_image_release_buffer(sima, ibuf, lock); } /* individual multiview images */ @@ -1919,7 +1912,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI unsigned char planes = ibuf->planes; const int totviews = (rr ? BLI_listbase_count(&rr->views) : BLI_listbase_count(&ima->views)); - if (!is_multilayer) { + if (!is_exr_rr) { ED_space_image_release_buffer(sima, ibuf, lock); } @@ -1929,9 +1922,9 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI const char *view = rr ? ((RenderView *) BLI_findlink(&rr->views, i))->name : ((ImageView *) BLI_findlink(&ima->views, i))->name; - if (is_multilayer) { + if (is_exr_rr) { BKE_scene_multiview_view_filepath_get(&scene->r, simopts->filepath, view, filepath); - ok_view = RE_WriteRenderResult(op->reports, rr, filepath, imf, false, view); + ok_view = RE_WriteRenderResult(op->reports, rr, filepath, imf, view, -1); save_image_post(op, ibuf, ima, ok_view, true, relbase, relative, do_newpath, filepath); } else { @@ -1959,14 +1952,14 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI ok &= ok_view; } - if (is_multilayer) { + if (is_exr_rr) { ED_space_image_release_buffer(sima, ibuf, lock); } } /* stereo (multiview) images */ else if (simopts->im_format.views_format == R_IMF_VIEWS_STEREO_3D) { if (imf->imtype == R_IMF_IMTYPE_MULTILAYER) { - ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, false, NULL); + ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, NULL, -1); save_image_post(op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath); ED_space_image_release_buffer(sima, ibuf, lock); } diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index f6c519ff27d..eff8ce6665b 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1081,6 +1081,11 @@ static void node_buts_output_linestyle(uiLayout *layout, bContext *UNUSED(C), Po uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE); } +static void node_shader_buts_bevel(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "samples", 0, NULL, ICON_NONE); +} + /* only once called */ static void node_shader_set_butfunc(bNodeType *ntype) { @@ -1212,6 +1217,9 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_OUTPUT_LINESTYLE: ntype->draw_buttons = node_buts_output_linestyle; break; + case SH_NODE_BEVEL: + ntype->draw_buttons = node_shader_buts_bevel; + break; } } diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 44803f8f7ee..2cf66c78db1 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -4093,6 +4093,11 @@ void node_bump(float strength, float dist, float height, vec3 N, vec3 surf_pos, result = normalize(strength * result + (1.0 - strength) * N); } +void node_bevel(float radius, vec3 N, out vec3 result) +{ + result = N; +} + /* output */ void node_output_material(Closure surface, Closure volume, float displacement, out Closure result) diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 1fa3b943524..451869415e7 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -374,21 +374,13 @@ static void openexr_header_metadata_callback(void *data, const char *propname, c static bool imb_save_openexr_half( - ImBuf *ibuf, const char *name, const int flags, const int totviews, - const char * (*getview)(void *base, int view_id), - ImBuf *(*getbuffer)(void *base, const int view_id)) + ImBuf *ibuf, const char *name, const int flags) { const int channels = ibuf->channels; const bool is_alpha = (channels >= 4) && (ibuf->planes == 32); const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ const int width = ibuf->x; const int height = ibuf->y; - const bool is_multiview = (flags & IB_multiview) && ibuf->userdata; - - BLI_assert((!is_multiview) || (getview && getbuffer)); - - std::vector <string> views; - int view_id; try { @@ -397,22 +389,14 @@ static bool imb_save_openexr_half( openexr_header_compression(&header, ibuf->foptions.flag & OPENEXR_COMPRESS); openexr_header_metadata(&header, ibuf); - /* create views when possible */ - for (view_id = 0; view_id < totviews; view_id ++) - views.push_back(is_multiview ? getview(ibuf->userdata, view_id) : ""); - - if (is_multiview) - addMultiView(header, views); - - for (view_id = 0; view_id < totviews; view_id ++) { - header.channels().insert(insertViewName("R", views, view_id), Channel(HALF)); - header.channels().insert(insertViewName("G", views, view_id), Channel(HALF)); - header.channels().insert(insertViewName("B", views, view_id), Channel(HALF)); - if (is_alpha) - header.channels().insert(insertViewName("A", views, view_id), Channel(HALF)); - if (is_zbuf) // z we do as float always - header.channels().insert(insertViewName("Z", views, view_id), Channel(Imf::FLOAT)); - } + /* create channels */ + header.channels().insert("R", Channel(HALF)); + header.channels().insert("G", Channel(HALF)); + header.channels().insert("B", Channel(HALF)); + if (is_alpha) + header.channels().insert("A", Channel(HALF)); + if (is_zbuf) // z we do as float always + header.channels().insert("Z", Channel(Imf::FLOAT)); FrameBuffer frameBuffer; @@ -421,65 +405,49 @@ static bool imb_save_openexr_half( OutputFile file(file_stream, header); /* we store first everything in half array */ - std::vector<RGBAZ> pixels(height * width * totviews); + std::vector<RGBAZ> pixels(height * width); + RGBAZ *to = &pixels[0]; int xstride = sizeof(RGBAZ); int ystride = xstride * width; - for (view_id = 0; view_id < totviews; view_id ++) { - ImBuf *view_ibuf = is_multiview ? getbuffer(ibuf->userdata, view_id) : ibuf; - const size_t offset = view_id * width * height; - RGBAZ *to = &pixels[offset]; - - /* TODO (dfelinto) - * In some cases we get NULL ibufs, it needs investigation, meanwhile prevent crash - * Multiview Render + Image Editor + OpenEXR + Multi-View - */ - if (view_ibuf == NULL) { - throw std::runtime_error(std::string("Missing data to write to ") + name); - } - - /* indicate used buffers */ - frameBuffer.insert(insertViewName("R", views, view_id), Slice(HALF, (char *) &pixels[offset].r, xstride, ystride)); - frameBuffer.insert(insertViewName("G", views, view_id), Slice(HALF, (char *) &pixels[offset].g, xstride, ystride)); - frameBuffer.insert(insertViewName("B", views, view_id), Slice(HALF, (char *) &pixels[offset].b, xstride, ystride)); - if (is_alpha) - frameBuffer.insert(insertViewName("A", views, view_id), Slice(HALF, (char *) &pixels[offset].a, xstride, ystride)); - if (is_zbuf) - frameBuffer.insert(insertViewName("Z", views, view_id), Slice(Imf::FLOAT, (char *)(view_ibuf->zbuf_float + (height - 1) * width), - sizeof(float), sizeof(float) * -width)); - if (view_ibuf->rect_float) { - float *from; - - for (int i = view_ibuf->y - 1; i >= 0; i--) { - from = view_ibuf->rect_float + channels * i * width; - - for (int j = view_ibuf->x; j > 0; j--) { - to->r = from[0]; - to->g = (channels >= 2) ? from[1] : from[0]; - to->b = (channels >= 3) ? from[2] : from[0]; - to->a = (channels >= 4) ? from[3] : 1.0f; - to++; from += channels; - } + /* indicate used buffers */ + frameBuffer.insert("R", Slice(HALF, (char *) &to->r, xstride, ystride)); + frameBuffer.insert("G", Slice(HALF, (char *) &to->g, xstride, ystride)); + frameBuffer.insert("B", Slice(HALF, (char *) &to->b, xstride, ystride)); + if (is_alpha) + frameBuffer.insert("A", Slice(HALF, (char *) &to->a, xstride, ystride)); + if (is_zbuf) + frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *)(ibuf->zbuf_float + (height - 1) * width), + sizeof(float), sizeof(float) * -width)); + if (ibuf->rect_float) { + float *from; + + for (int i = ibuf->y - 1; i >= 0; i--) { + from = ibuf->rect_float + channels * i * width; + + for (int j = ibuf->x; j > 0; j--) { + to->r = from[0]; + to->g = (channels >= 2) ? from[1] : from[0]; + to->b = (channels >= 3) ? from[2] : from[0]; + to->a = (channels >= 4) ? from[3] : 1.0f; + to++; from += channels; } } - else { - unsigned char *from; + } + else { + unsigned char *from; - for (int i = view_ibuf->y - 1; i >= 0; i--) { - from = (unsigned char *)view_ibuf->rect + 4 * i * width; + for (int i = ibuf->y - 1; i >= 0; i--) { + from = (unsigned char *)ibuf->rect + 4 * i * width; - for (int j = view_ibuf->x; j > 0; j--) { - to->r = srgb_to_linearrgb((float)from[0] / 255.0f); - to->g = srgb_to_linearrgb((float)from[1] / 255.0f); - to->b = srgb_to_linearrgb((float)from[2] / 255.0f); - to->a = channels >= 4 ? (float)from[3] / 255.0f : 1.0f; - to++; from += 4; - } + for (int j = ibuf->x; j > 0; j--) { + to->r = srgb_to_linearrgb((float)from[0] / 255.0f); + to->g = srgb_to_linearrgb((float)from[1] / 255.0f); + to->b = srgb_to_linearrgb((float)from[2] / 255.0f); + to->a = channels >= 4 ? (float)from[3] / 255.0f : 1.0f; + to++; from += 4; } } - - if (is_multiview) - IMB_freeImBuf(view_ibuf); } exr_printf("OpenEXR-save: Writing OpenEXR file of height %d.\n", height); @@ -498,21 +466,13 @@ static bool imb_save_openexr_half( } static bool imb_save_openexr_float( - ImBuf *ibuf, const char *name, const int flags, const int totviews, - const char * (*getview)(void *base, const int view_id), - ImBuf *(*getbuffer)(void *base, const int view_id)) + ImBuf *ibuf, const char *name, const int flags) { const int channels = ibuf->channels; const bool is_alpha = (channels >= 4) && (ibuf->planes == 32); const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ const int width = ibuf->x; const int height = ibuf->y; - const bool is_multiview = (flags & IB_multiview) && ibuf->userdata; - - BLI_assert((!is_multiview) || (getview && getbuffer)); - - std::vector <string> views; - int view_id; try { @@ -521,22 +481,14 @@ static bool imb_save_openexr_float( openexr_header_compression(&header, ibuf->foptions.flag & OPENEXR_COMPRESS); openexr_header_metadata(&header, ibuf); - /* create views when possible */ - for (view_id = 0; view_id < totviews; view_id ++) - views.push_back(is_multiview ? getview(ibuf->userdata, view_id) : ""); - - if (is_multiview) - addMultiView(header, views); - - for (view_id = 0; view_id < totviews; view_id ++) { - header.channels().insert(insertViewName("R", views, view_id), Channel(Imf::FLOAT)); - header.channels().insert(insertViewName("G", views, view_id), Channel(Imf::FLOAT)); - header.channels().insert(insertViewName("B", views, view_id), Channel(Imf::FLOAT)); - if (is_alpha) - header.channels().insert(insertViewName("A", views, view_id), Channel(Imf::FLOAT)); - if (is_zbuf) - header.channels().insert(insertViewName("Z", views, view_id), Channel(Imf::FLOAT)); - } + /* create channels */ + header.channels().insert("R", Channel(Imf::FLOAT)); + header.channels().insert("G", Channel(Imf::FLOAT)); + header.channels().insert("B", Channel(Imf::FLOAT)); + if (is_alpha) + header.channels().insert("A", Channel(Imf::FLOAT)); + if (is_zbuf) + header.channels().insert("Z", Channel(Imf::FLOAT)); FrameBuffer frameBuffer; @@ -547,36 +499,22 @@ static bool imb_save_openexr_float( int xstride = sizeof(float) * channels; int ystride = -xstride * width; - for (view_id = 0; view_id < totviews; view_id ++) { - float *rect[4] = {NULL, NULL, NULL, NULL}; - ImBuf *view_ibuf = is_multiview ? getbuffer(ibuf->userdata, view_id) : ibuf; - - /* TODO (dfelinto) - * In some cases we get NULL ibufs, it needs investigation, meanwhile prevent crash - * Multiview Render + Image Editor + OpenEXR + Multi-View - */ - if (view_ibuf == NULL) { - throw std::runtime_error(std::string("Missing data to write to ") + name); - } + /* last scanline, stride negative */ + float *rect[4] = {NULL, NULL, NULL, NULL}; + rect[0] = ibuf->rect_float + channels * (height - 1) * width; + rect[1] = (channels >= 2) ? rect[0] + 1 : rect[0]; + rect[2] = (channels >= 3) ? rect[0] + 2 : rect[0]; + rect[3] = (channels >= 4) ? rect[0] + 3 : rect[0]; /* red as alpha, is this needed since alpha isn't written? */ + + frameBuffer.insert("R", Slice(Imf::FLOAT, (char *)rect[0], xstride, ystride)); + frameBuffer.insert("G", Slice(Imf::FLOAT, (char *)rect[1], xstride, ystride)); + frameBuffer.insert("B", Slice(Imf::FLOAT, (char *)rect[2], xstride, ystride)); + if (is_alpha) + frameBuffer.insert("A", Slice(Imf::FLOAT, (char *)rect[3], xstride, ystride)); + if (is_zbuf) + frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *) (ibuf->zbuf_float + (height - 1) * width), + sizeof(float), sizeof(float) * -width)); - /* last scanline, stride negative */ - rect[0] = view_ibuf->rect_float + channels * (height - 1) * width; - rect[1] = (channels >= 2) ? rect[0] + 1 : rect[0]; - rect[2] = (channels >= 3) ? rect[0] + 2 : rect[0]; - rect[3] = (channels >= 4) ? rect[0] + 3 : rect[0]; /* red as alpha, is this needed since alpha isn't written? */ - - frameBuffer.insert(insertViewName("R", views, view_id), Slice(Imf::FLOAT, (char *)rect[0], xstride, ystride)); - frameBuffer.insert(insertViewName("G", views, view_id), Slice(Imf::FLOAT, (char *)rect[1], xstride, ystride)); - frameBuffer.insert(insertViewName("B", views, view_id), Slice(Imf::FLOAT, (char *)rect[2], xstride, ystride)); - if (is_alpha) - frameBuffer.insert(insertViewName("A", views, view_id), Slice(Imf::FLOAT, (char *)rect[3], xstride, ystride)); - if (is_zbuf) - frameBuffer.insert(insertViewName("Z", views, view_id), Slice(Imf::FLOAT, (char *) (view_ibuf->zbuf_float + (height - 1) * width), - sizeof(float), sizeof(float) * -width)); - - if (is_multiview) - IMB_freeImBuf(view_ibuf); - } file.setFrameBuffer(frameBuffer); file.writePixels(height); } @@ -599,50 +537,16 @@ int imb_save_openexr(struct ImBuf *ibuf, const char *name, int flags) } if (ibuf->foptions.flag & OPENEXR_HALF) - return (int) imb_save_openexr_half(ibuf, name, flags, 1, NULL, NULL); + return (int) imb_save_openexr_half(ibuf, name, flags); else { /* when no float rect, we save as half (16 bits is sufficient) */ if (ibuf->rect_float == NULL) - return (int) imb_save_openexr_half(ibuf, name, flags, 1, NULL, NULL); + return (int) imb_save_openexr_half(ibuf, name, flags); else - return (int) imb_save_openexr_float(ibuf, name, flags, 1, NULL, NULL); + return (int) imb_save_openexr_float(ibuf, name, flags); } } -static bool imb_save_openexr_multiview( - ImBuf *ibuf, const char *name, const int flags, const int totviews, - const char *(*getview)(void *base, const int view_id), - ImBuf *(*getbuffer)(void *base, const int view_id)) -{ - if (flags & IB_mem) { - printf("OpenEXR-save: Create multiview EXR in memory CURRENTLY NOT SUPPORTED !\n"); - imb_addencodedbufferImBuf(ibuf); - ibuf->encodedsize = 0; - return false; - } - - if (ibuf->foptions.flag & OPENEXR_HALF) - return imb_save_openexr_half(ibuf, name, flags, totviews, getview, getbuffer); - else { - /* when no float rect, we save as half (16 bits is sufficient) */ - if (ibuf->rect_float == NULL) - return imb_save_openexr_half(ibuf, name, flags, totviews, getview, getbuffer); - else - return imb_save_openexr_float(ibuf, name, flags, totviews, getview, getbuffer); - } -} - -/* Save single-layer multiview OpenEXR - * If we have more multiview formats in the future, the function below could be incorporated - * in our ImBuf write functions, meanwhile this is an OpenEXR special case only */ -bool IMB_exr_multiview_save( - ImBuf *ibuf, const char *name, const int flags, const int totviews, - const char *(*getview)(void *base, const int view_id), - ImBuf *(*getbuffer)(void *base, const int view_id)) -{ - return imb_save_openexr_multiview(ibuf, name, flags, totviews, getview, getbuffer); -} - /* ********************* Nicer API, MultiLayer and with Tile file support ************************************ */ /* naming rules: @@ -841,7 +745,7 @@ void IMB_exr_add_channel(void *handle, if (layname && layname[0] != '\0') { imb_exr_insert_view_name(echan->name, echan->m->name.c_str(), echan->m->view.c_str()); } - else if (data->multiView->size() > 1) { + else if (data->multiView->size() >= 1) { std::string raw_name = insertViewName(echan->m->name, *data->multiView, echan->view_id); BLI_strncpy(echan->name, raw_name.c_str(), sizeof(echan->name)); } @@ -1071,7 +975,7 @@ float *IMB_exr_channel_rect(void *handle, const char *layname, const char *pass imb_exr_insert_view_name(temp_buf, name, viewname); BLI_strncpy(name, temp_buf, sizeof(name)); } - else if (data->multiView->size() > 1) { + else if (data->multiView->size() >= 1) { const int view_id = std::max(0, imb_exr_get_multiView_id(*data->multiView, viewname)); std::string raw_name = insertViewName(name, *data->multiView, view_id); BLI_strncpy(name, raw_name.c_str(), sizeof(name)); @@ -1199,64 +1103,10 @@ void IMB_exrtile_write_channels(void *handle, int partx, int party, int level, c } } -/* called only when handle has all views */ -void IMB_exrmultiview_write_channels(void *handle, const char *viewname) -{ - ExrHandle *data = (ExrHandle *)handle; - const int view_id = viewname ? imb_exr_get_multiView_id(*data->multiView, viewname) : -1; - int numparts = (view_id == -1 ? data->parts : view_id + 1); - std::vector <FrameBuffer> frameBuffers(numparts); - std::vector <OutputPart> outputParts; - ExrChannel *echan; - int i, part; - - if (data->channels.first == NULL) - return; - - exr_printf("\nIMB_exrmultiview_write_channels()\n"); - - for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { - if (view_id != -1 && echan->view_id != view_id) - continue; - - part = (view_id == -1 ? echan->m->part_number : echan->view_id); - - /* last scanline, stride negative */ - float *rect = echan->rect + echan->xstride * (data->height - 1) * data->width; - frameBuffers[part].insert(echan->m->internal_name, - Slice(Imf::FLOAT, - (char *)rect, - echan->xstride * sizeof(float), - -echan->ystride * sizeof(float)) - ); - } - - for (i = 0; i < numparts; i++) { - OutputPart out(*data->mpofile, i); - out.setFrameBuffer(frameBuffers[i]); - outputParts.push_back(out); - } - - try { - for (i = 0; i < numparts; i++) { - if (view_id != -1 && i != view_id) - continue; - - outputParts[i].writePixels(data->height); - } - } - catch (const std::exception& exc) { - std::cerr << "OpenEXR-write Multi Part: ERROR: " << exc.what() << std::endl; - } -} - void IMB_exr_read_channels(void *handle) { ExrHandle *data = (ExrHandle *)handle; - ExrChannel *echan; int numparts = data->ifile->parts(); - std::vector<FrameBuffer> frameBuffers(numparts); - std::vector<InputPart> inputParts; /* check if exr was saved with previous versions of blender which flipped images */ const StringAttribute *ta = data->ifile->header(0).findTypedAttribute <StringAttribute> ("BlenderMultiChannel"); @@ -1264,37 +1114,56 @@ void IMB_exr_read_channels(void *handle) exr_printf("\nIMB_exr_read_channels\n%s %-6s %-22s \"%s\"\n---------------------------------------------------------------------\n", "p", "view", "name", "internal_name"); - for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { - exr_printf("%d %-6s %-22s \"%s\"\n", echan->m->part_number, echan->m->view.c_str(), echan->m->name.c_str(), echan->m->internal_name.c_str()); + for (int i = 0; i < numparts; i++) { + /* Read part header. */ + InputPart in(*data->ifile, i); + Header header = in.header(); + Box2i dw = header.dataWindow(); + + /* Insert all matching channel into framebuffer. */ + FrameBuffer frameBuffer; + ExrChannel *echan; + + for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { + if(echan->m->part_number != i) { + continue; + } + + exr_printf("%d %-6s %-22s \"%s\"\n", echan->m->part_number, echan->m->view.c_str(), echan->m->name.c_str(), echan->m->internal_name.c_str()); + + if (echan->rect) { + float *rect = echan->rect; + size_t xstride = echan->xstride * sizeof(float); + size_t ystride = echan->ystride * sizeof(float); + + if (!flip) { + /* inverse correct first pixel for datawindow coordinates */ + rect -= echan->xstride * (dw.min.x - dw.min.y * data->width); + /* move to last scanline to flip to Blender convention */ + rect += echan->xstride * (data->height - 1) * data->width; + ystride = -ystride; + } + else { + /* inverse correct first pixel for datawindow coordinates */ + rect -= echan->xstride * (dw.min.x + dw.min.y * data->width); + } - if (echan->rect) { - if (flip) - frameBuffers[echan->m->part_number].insert(echan->m->internal_name, Slice(Imf::FLOAT, (char *)echan->rect, - echan->xstride * sizeof(float), echan->ystride * sizeof(float))); + frameBuffer.insert(echan->m->internal_name, Slice(Imf::FLOAT, (char *)rect, xstride, ystride)); + } else - frameBuffers[echan->m->part_number].insert(echan->m->internal_name, Slice(Imf::FLOAT, (char *)(echan->rect + echan->xstride * (data->height - 1) * data->width), - echan->xstride * sizeof(float), -echan->ystride * sizeof(float))); + printf("warning, channel with no rect set %s\n", echan->m->internal_name.c_str()); } - else - printf("warning, channel with no rect set %s\n", echan->m->internal_name.c_str()); - } - - for (int i = 0; i < numparts; i++) { - InputPart in (*data->ifile, i); - in.setFrameBuffer(frameBuffers[i]); - inputParts.push_back(in); - } - try { - for (int i = 0; i < numparts; i++) { - Header header = inputParts[i].header(); - exr_printf("readPixels:readPixels[%d]: min.y: %d, max.y: %d\n", i, header.dataWindow().min.y, header.dataWindow().max.y); - inputParts[i].readPixels(header.dataWindow().min.y, header.dataWindow().max.y); - inputParts[i].readPixels(0, data->height - 1); + /* Read pixels. */ + try { + in.setFrameBuffer(frameBuffer); + exr_printf("readPixels:readPixels[%d]: min.y: %d, max.y: %d\n", i, dw.min.y, dw.max.y); + in.readPixels(dw.min.y, dw.max.y); + } + catch (const std::exception& exc) { + std::cerr << "OpenEXR-readPixels: ERROR: " << exc.what() << std::endl; + break; } - } - catch (const std::exception& exc) { - std::cerr << "OpenEXR-readPixels: ERROR: " << exc.what() << std::endl; } } @@ -1336,69 +1205,6 @@ void IMB_exr_multilayer_convert(void *handle, void *base, } } -void IMB_exr_multiview_convert(void *handle, void *base, - void (*addview)(void *base, const char *str), - void (*addbuffer)(void *base, const char *str, ImBuf *ibuf, const int frame), - const int frame) -{ - ExrHandle *data = (ExrHandle *)handle; - MultiPartInputFile *file = data->ifile; - ExrLayer *lay; - ExrPass *pass; - ImBuf *ibuf = NULL; - const bool is_alpha = exr_has_alpha(*file); - Box2i dw = file->header(0).dataWindow(); - const size_t width = dw.max.x - dw.min.x + 1; - const size_t height = dw.max.y - dw.min.y + 1; - const bool is_depth = exr_has_zbuffer(*file); - - /* add views to RenderResult */ - for (StringVector::const_iterator i = data->multiView->begin(); i != data->multiView->end(); ++i) { - addview(base, (*i).c_str()); - } - - if (BLI_listbase_is_empty(&data->layers)) { - printf("cannot convert multiviews, no views in handle\n"); - return; - } - - /* there is one float/pass per layer (layer here is a view) */ - BLI_assert(BLI_listbase_count_ex(&data->layers, 2) == 1); - lay = (ExrLayer *)data->layers.first; - for (pass = (ExrPass *)lay->passes.first; pass; pass = pass->next) { - if (STREQ(pass->chan_id, "RGB") || STREQ(pass->chan_id, "RGBA")) { - ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, IB_rectfloat); - - if (!ibuf) { - printf("error creating multiview buffer\n"); - return; - } - - IMB_buffer_float_from_float( - ibuf->rect_float, pass->rect, pass->totchan, - IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false, - ibuf->x, ibuf->y, ibuf->x, ibuf->x); - - if (hasXDensity(file->header(0))) { - ibuf->ppm[0] = xDensity(file->header(0)) * 39.3700787f; - ibuf->ppm[1] = ibuf->ppm[0] * (double)file->header(0).pixelAspectRatio(); - } - - if (is_depth) { - ExrPass *zpass; - for (zpass = (ExrPass *)lay->passes.first; zpass; zpass = zpass->next) { - if (STREQ(zpass->chan_id, "Z") && STREQ(zpass->view, pass->view)) { - addzbuffloatImBuf(ibuf); - memcpy(ibuf->zbuf_float, zpass->rect, sizeof(float) * ibuf->x * ibuf->y); - } - } - } - - addbuffer(base, pass->view, ibuf, frame); - } - } -} - void IMB_exr_close(void *handle) { ExrHandle *data = (ExrHandle *)handle; @@ -1863,49 +1669,20 @@ static void imb_exr_type_by_channels(ChannelList& channels, StringVector& views, else { *r_singlelayer = true; *r_multilayer = false; - *r_multiview = false; } BLI_assert(r_singlelayer != r_multilayer); } -bool IMB_exr_has_singlelayer_multiview(void *handle) -{ - ExrHandle *data = (ExrHandle *)handle; - MultiPartInputFile *file = data->ifile; - std::set <std::string> layerNames; - const ChannelList& channels = file->header(0).channels(); - const StringAttribute *comments; - - if (exr_has_multiview(*file) == false) - return false; - - comments = file->header(0).findTypedAttribute<StringAttribute>("BlenderMultiChannel"); - - if (comments) - return false; - - /* will not include empty layer names */ - channels.layers(layerNames); - - /* returns false if any layer differs from views list */ - if (layerNames.size()) - for (std::set<string>::iterator i = layerNames.begin(); i != layerNames.end(); i++) - if (imb_exr_get_multiView_id(*data->multiView, *i) == -1) - return false; - - return true; -} - -bool IMB_exr_has_multilayer(void *handle) -{ - ExrHandle *data = (ExrHandle *)handle; - return imb_exr_is_multilayer_file(*data->ifile); -} - static bool exr_has_multiview(MultiPartInputFile& file) { - return hasMultiView(file.header(0)); + for (int p = 0; p < file.parts(); p++) { + if (hasMultiView(file.header(p))) { + return true; + } + } + + return false; } static bool exr_has_multipart_file(MultiPartInputFile& file) @@ -1929,6 +1706,12 @@ static bool imb_exr_is_multi(MultiPartInputFile& file) return false; } +bool IMB_exr_has_multilayer(void *handle) +{ + ExrHandle *data = (ExrHandle *)handle; + return imb_exr_is_multi(*data->ifile); +} + struct ImBuf *imb_load_openexr(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { struct ImBuf *ibuf = NULL; diff --git a/source/blender/imbuf/intern/openexr/openexr_multi.h b/source/blender/imbuf/intern/openexr/openexr_multi.h index 0fa0f64bdce..d9517d13cc4 100644 --- a/source/blender/imbuf/intern/openexr/openexr_multi.h +++ b/source/blender/imbuf/intern/openexr/openexr_multi.h @@ -68,7 +68,6 @@ float *IMB_exr_channel_rect(void *handle, const char *layname, const char *pass void IMB_exr_read_channels(void *handle); void IMB_exr_write_channels(void *handle); void IMB_exrtile_write_channels(void *handle, int partx, int party, int level, const char *viewname); -void IMB_exrmultiview_write_channels(void *handle, const char *viewname); void IMB_exr_clear_channels(void *handle); void IMB_exr_multilayer_convert( @@ -78,23 +77,11 @@ void IMB_exr_multilayer_convert( void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id, const char *view)); -void IMB_exr_multiview_convert( - void *handle, void *base, - void (*addview)(void *base, const char *str), - void (*addbuffer)(void *base, const char *str, struct ImBuf *ibuf, const int frame), - const int frame); - -bool IMB_exr_multiview_save( - struct ImBuf *ibuf, const char *name, const int flags, const int totviews, - const char *(*getview)(void *base, int view_id), - struct ImBuf *(*getbuffer)(void *base, const int view_id)); - void IMB_exr_close(void *handle); void IMB_exr_add_view(void *handle, const char *name); bool IMB_exr_has_multilayer(void *handle); -bool IMB_exr_has_singlelayer_multiview(void *handle); #ifdef __cplusplus } // extern "C" diff --git a/source/blender/imbuf/intern/openexr/openexr_stub.cpp b/source/blender/imbuf/intern/openexr/openexr_stub.cpp index 498e246a915..05fddcb5fa5 100644 --- a/source/blender/imbuf/intern/openexr/openexr_stub.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_stub.cpp @@ -48,7 +48,6 @@ float *IMB_exr_channel_rect (void * /*handle*/, const char * /*layname*/ void IMB_exr_read_channels (void * /*handle*/) { } void IMB_exr_write_channels (void * /*handle*/) { } void IMB_exrtile_write_channels (void * /*handle*/, int /*partx*/, int /*party*/, int /*level*/, const char * /*viewname*/) { } -void IMB_exrmultiview_write_channels(void * /*handle*/, const char * /*viewname*/) { } void IMB_exr_clear_channels (void * /*handle*/) { } void IMB_exr_multilayer_convert( @@ -60,24 +59,7 @@ void IMB_exr_multilayer_convert( { } -void IMB_exr_multiview_convert( - void * /*handle*/, void * /*base*/, - void (* /*addview*/)(void *base, const char *str), - void (* /*addbuffer*/)(void *base, const char *str, struct ImBuf *ibuf, const int frame), - const int /*frame*/) -{ -} - -bool IMB_exr_multiview_save( - struct ImBuf * /*ibuf*/, const char * /*name*/, const int /*flags*/, const int /*totviews*/, - const char *(* /*getview*/)(void *base, const int view_id), - struct ImBuf *(* /*getbuffer*/)(void *base, const int view_id)) -{ - return false; -} - void IMB_exr_close (void * /*handle*/) { } void IMB_exr_add_view(void * /*handle*/, const char * /*name*/) { } bool IMB_exr_has_multilayer(void * /*handle*/) { return false; } -bool IMB_exr_has_singlelayer_multiview(void * /*handle*/) { return false; } diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 9147d0a0bc8..5db2d534dbe 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -4410,6 +4410,16 @@ static void def_sh_tangent(StructRNA *srna) RNA_def_struct_sdna_from(srna, "bNode", NULL); } +static void def_sh_bevel(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "samples", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "custom1"); + RNA_def_property_range(prop, 2, 16); + RNA_def_property_ui_text(prop, "Samples", "Number of rays to trace per shader evaluation"); + RNA_def_property_update(prop, 0, "rna_Node_update"); +} static void def_sh_subsurface(StructRNA *srna) { diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index d65b71a35e5..a6e04510b03 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -193,6 +193,7 @@ set(SRC shader/nodes/node_shader_script.c shader/nodes/node_shader_subsurface_scattering.c shader/nodes/node_shader_tangent.c + shader/nodes/node_shader_bevel.c shader/nodes/node_shader_tex_brick.c shader/nodes/node_shader_tex_checker.c shader/nodes/node_shader_tex_coord.c diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 08c4924150e..62a92e8d084 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -78,6 +78,7 @@ void register_node_type_sh_tex_brick(void); void register_node_type_sh_tex_pointdensity(void); void register_node_type_sh_attribute(void); +void register_node_type_sh_bevel(void); void register_node_type_sh_geometry(void); void register_node_type_sh_light_path(void); void register_node_type_sh_light_falloff(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 783e1a388c1..a18ee154af8 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -127,6 +127,7 @@ DefNode( ShaderNode, SH_NODE_UVMAP, def_sh_uvmap, "UV DefNode( ShaderNode, SH_NODE_UVALONGSTROKE, def_sh_uvalongstroke, "UVALONGSTROKE", UVAlongStroke, "UV Along Stroke", "" ) DefNode( ShaderNode, SH_NODE_SEPXYZ, 0, "SEPXYZ", SeparateXYZ, "Separate XYZ", "" ) DefNode( ShaderNode, SH_NODE_COMBXYZ, 0, "COMBXYZ", CombineXYZ, "Combine XYZ", "" ) +DefNode( ShaderNode, SH_NODE_BEVEL, def_sh_bevel, "BEVEL", Bevel, "Bevel", "" ) DefNode( CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" ) DefNode( CompositorNode, CMP_NODE_RGB, 0, "RGB", RGB, "RGB", "" ) diff --git a/source/blender/nodes/shader/nodes/node_shader_bevel.c b/source/blender/nodes/shader/nodes/node_shader_bevel.c new file mode 100644 index 00000000000..dd9bc91e2d1 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_bevel.c @@ -0,0 +1,70 @@ +/* + * ***** 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_bevel_in[] = { + { SOCK_FLOAT, 0, N_("Radius"), 0.05f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, + { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_bevel_out[] = { + { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void node_shader_init_bevel(bNodeTree *UNUSED(ntree), bNode *node) +{ + node->custom1 = 4; /* samples */ +} + +static int gpu_shader_bevel(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +{ + if (!in[1].link) { + GPU_link(mat, "direction_transform_m4v3", GPU_builtin(GPU_VIEW_NORMAL), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &in[1].link); + } + + return GPU_stack_link(mat, node, "node_bevel", in, out); +} + +/* node type definition */ +void register_node_type_sh_bevel(void) +{ + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_BEVEL, "Bevel", NODE_CLASS_INPUT, 0); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, sh_node_bevel_in, sh_node_bevel_out); + node_type_init(&ntype, node_shader_init_bevel); + node_type_storage(&ntype, "", NULL, NULL); + node_type_gpu(&ntype, gpu_shader_bevel); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index c19c332c677..243aff8ae54 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -316,7 +316,7 @@ void RE_PreviewRender(struct Render *re, struct Main *bmain, struct Scene *scene bool RE_ReadRenderResult(struct Scene *scene, struct Scene *scenode); bool RE_WriteRenderResult( struct ReportList *reports, RenderResult *rr, const char *filename, - struct ImageFormatData *imf, const bool multiview, const char *view); + struct ImageFormatData *imf, const char *view, const int layer); struct RenderResult *RE_MultilayerConvert( void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty); @@ -348,6 +348,7 @@ void RE_zbuf_accumulate_vecblur( int RE_seq_render_active(struct Scene *scene, struct RenderData *rd); bool RE_layers_have_name(struct RenderResult *result); +bool RE_passes_have_name(struct RenderLayer *rl); struct RenderPass *RE_pass_find_by_name(volatile struct RenderLayer *rl, const char *name, const char *viewname); struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname); @@ -393,7 +394,7 @@ void RE_updateRenderInstances(Render *re, int flag); /******* defined in render_result.c *********/ -bool RE_HasFakeLayer(RenderResult *res); +bool RE_HasCombinedLayer(RenderResult *res); bool RE_RenderResult_is_stereo(RenderResult *res); struct RenderView *RE_RenderViewGetById(struct RenderResult *res, const int view_id); struct RenderView *RE_RenderViewGetByName(struct RenderResult *res, const char *viewname); diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h index 4057d8c1052..8d293c938c7 100644 --- a/source/blender/render/intern/include/render_result.h +++ b/source/blender/render/intern/include/render_result.h @@ -115,6 +115,7 @@ void render_result_rect_get_pixels(struct RenderResult *rr, void render_result_views_shallowcopy(struct RenderResult *dst, struct RenderResult *src); void render_result_views_shallowdelete(struct RenderResult *rr); +bool render_result_has_views(struct RenderResult *rr); #endif /* __RENDER_RESULT_H__ */ diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 7a8f0d3ada7..f351a990dba 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -385,6 +385,7 @@ void RE_AcquireResultImageViews(Render *re, RenderResult *rr) render_result_views_shallowcopy(rr, re->result); rv = rr->views.first; + rr->have_combined = (rv->rectf != NULL); /* active layer */ rl = render_get_active_layer(re, re->result); @@ -403,7 +404,6 @@ void RE_AcquireResultImageViews(Render *re, RenderResult *rr) } } - rr->have_combined = (rv->rectf != NULL); rr->layers = re->result->layers; rr->xof = re->disprect.xmin; rr->yof = re->disprect.ymin; @@ -442,11 +442,14 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id) /* actview view */ rv = RE_RenderViewGetById(re->result, view_id); + rr->have_combined = (rv->rectf != NULL); rr->rectf = rv->rectf; rr->rectz = rv->rectz; rr->rect32 = rv->rect32; + rr->have_combined = (rv->rectf != NULL); + /* active layer */ rl = render_get_active_layer(re, re->result); @@ -458,7 +461,6 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id) rr->rectz = RE_RenderLayerGetPass(rl, RE_PASSNAME_Z, rv->name); } - rr->have_combined = (rv->rectf != NULL); rr->layers = re->result->layers; rr->views = re->result->views; @@ -3333,19 +3335,18 @@ void RE_RenderFreestyleExternal(Render *re) bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scene, const bool stamp, char *name) { - bool is_mono; bool ok = true; RenderData *rd = &scene->r; if (!rr) return false; - is_mono = BLI_listbase_count_ex(&rr->views, 2) < 2; + bool is_mono = BLI_listbase_count_ex(&rr->views, 2) < 2; + bool is_exr_rr = ELEM(rd->im_format.imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER); - if (ELEM(rd->im_format.imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER) && - rd->im_format.views_format == R_IMF_VIEWS_MULTIVIEW) + if (rd->im_format.views_format == R_IMF_VIEWS_MULTIVIEW && is_exr_rr) { - ok = RE_WriteRenderResult(reports, rr, name, &rd->im_format, true, NULL); + ok = RE_WriteRenderResult(reports, rr, name, &rd->im_format, NULL, -1); render_print_save_message(reports, name, ok, errno); } @@ -3363,33 +3364,34 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen BKE_scene_multiview_view_filepath_get(&scene->r, filepath, rv->name, name); } - if (rd->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) { - ok = RE_WriteRenderResult(reports, rr, name, &rd->im_format, false, rv->name); + if (is_exr_rr) { + ok = RE_WriteRenderResult(reports, rr, name, &rd->im_format, rv->name, -1); render_print_save_message(reports, name, ok, errno); - } - else { - ImBuf *ibuf = render_result_rect_to_ibuf(rr, rd, view_id); - - IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings, - &scene->display_settings, &rd->im_format); - - ok = render_imbuf_write_stamp_test(reports, scene, rr, ibuf, name, &rd->im_format, stamp); /* optional preview images for exr */ - if (ok && rd->im_format.imtype == R_IMF_IMTYPE_OPENEXR && (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) { + if (ok && (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) { ImageFormatData imf = rd->im_format; imf.imtype = R_IMF_IMTYPE_JPEG90; if (BLI_testextensie(name, ".exr")) name[strlen(name) - 4] = 0; BKE_image_path_ensure_ext_from_imformat(name, &imf); - ibuf->planes = 24; - IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings, - &scene->display_settings, &imf); + ImBuf *ibuf = render_result_rect_to_ibuf(rr, rd, view_id); + ibuf->planes = 24; ok = render_imbuf_write_stamp_test(reports, scene, rr, ibuf, name, &imf, stamp); + + IMB_freeImBuf(ibuf); } + } + else { + ImBuf *ibuf = render_result_rect_to_ibuf(rr, rd, view_id); + + IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings, + &scene->display_settings, &rd->im_format); + + ok = render_imbuf_write_stamp_test(reports, scene, rr, ibuf, name, &rd->im_format, stamp); /* imbuf knows which rects are not part of ibuf */ IMB_freeImBuf(ibuf); @@ -3400,7 +3402,7 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen BLI_assert(scene->r.im_format.views_format == R_IMF_VIEWS_STEREO_3D); if (rd->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) { - printf("Stereo 3D not support for MultiLayer image: %s\n", name); + printf("Stereo 3D not supported for MultiLayer image: %s\n", name); } else { ImBuf *ibuf_arr[3] = {NULL}; @@ -3420,7 +3422,7 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen ok = render_imbuf_write_stamp_test(reports, scene, rr, ibuf_arr[2], name, &rd->im_format, stamp); /* optional preview images for exr */ - if (ok && rd->im_format.imtype == R_IMF_IMTYPE_OPENEXR && + if (ok && is_exr_rr && (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) { ImageFormatData imf = rd->im_format; @@ -3432,9 +3434,6 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen BKE_image_path_ensure_ext_from_imformat(name, &imf); ibuf_arr[2]->planes = 24; - IMB_colormanagement_imbuf_for_write(ibuf_arr[2], true, false, &scene->view_settings, - &scene->display_settings, &imf); - ok = render_imbuf_write_stamp_test(reports, scene, rr, ibuf_arr[2], name, &rd->im_format, stamp); } @@ -4049,7 +4048,7 @@ bool RE_WriteEnvmapResult(struct ReportList *reports, Scene *scene, EnvMap *env, } } -/* used in the interface to decide whether to show layers */ +/* Used in the interface to decide whether to show layers or passes. */ bool RE_layers_have_name(struct RenderResult *rr) { switch (BLI_listbase_count_ex(&rr->layers, 2)) { @@ -4063,6 +4062,17 @@ bool RE_layers_have_name(struct RenderResult *rr) return false; } +bool RE_passes_have_name(struct RenderLayer *rl) +{ + for (RenderPass *rp = rl->passes.first; rp; rp = rp->next) { + if (!STREQ(rp->name, "Combined")) { + return true; + } + } + + return false; +} + RenderPass *RE_pass_find_by_name(volatile RenderLayer *rl, const char *name, const char *viewname) { RenderPass *rp = NULL; diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index aa0c7357302..631503bdad5 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -585,7 +585,7 @@ static void *ml_addlayer_cb(void *base, const char *str) rl = MEM_callocN(sizeof(RenderLayer), "new render layer"); BLI_addtail(&rr->layers, rl); - + BLI_strncpy(rl->name, str, EXR_LAY_MAXNAME); return rl; } @@ -756,6 +756,12 @@ void render_result_views_new(RenderResult *rr, RenderData *rd) } } +bool render_result_has_views(RenderResult *rr) +{ + RenderView *rv = rr->views.first; + return (rv && (rv->next || rv->name[0])); +} + /*********************************** Merge ***********************************/ static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize) @@ -820,101 +826,124 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart) } } -/* called from within UI and render pipeline, saves both rendered result as a file-read result - * if multiview is true saves all views in a multiview exr - * else if view is not NULL saves single view - * else saves stereo3d - */ -bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, ImageFormatData *imf, const bool multiview, const char *view) +/* Called from the UI and render pipeline, to save multilayer and multiview + * images, optionally isolating a specific, view, layer or RGBA/Z pass. */ +bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, ImageFormatData *imf, const char *view, int layer) { - RenderLayer *rl; - RenderPass *rpass; - RenderView *rview; void *exrhandle = IMB_exr_get_handle(); - bool success; - int a, nr; - const char *chan_view = NULL; - int compress = (imf ? imf->exr_codec : 0); - size_t width, height; - - const bool is_mono = view && !multiview; - const bool use_half_float = (imf != NULL) ? (imf->depth == R_IMF_CHAN_DEPTH_16) : false; - - width = rr->rectx; - height = rr->recty; + const bool half_float = (imf && imf->depth == R_IMF_CHAN_DEPTH_16); + const bool multi_layer = !(imf && imf->imtype == R_IMF_IMTYPE_OPENEXR); + const bool write_z = !multi_layer && (imf && (imf->flag & R_IMF_FLAG_ZBUF)); - if (imf && imf->imtype == R_IMF_IMTYPE_OPENEXR && multiview) { - /* single layer OpenEXR */ - const char *RGBAZ[] = {"R", "G", "B", "A", "Z"}; - for (nr = 0, rview = rr->views.first; rview; rview = rview->next, nr++) { - IMB_exr_add_view(exrhandle, rview->name); + /* Write first layer if not multilayer and no layer was specified. */ + if (!multi_layer && layer == -1) { + layer = 0; + } - if (rview->rectf) { - for (a = 0; a < 4; a++) { - IMB_exr_add_channel(exrhandle, "", RGBAZ[a], - rview->name, 4, 4 * width, rview->rectf + a, - use_half_float); - } - if (rview->rectz) { - /* Z pass is always stored as float. */ - IMB_exr_add_channel(exrhandle, "", RGBAZ[4], - rview->name, 1, width, rview->rectz, - false); - } + /* First add views since IMB_exr_add_channel checks number of views. */ + if (render_result_has_views(rr)) { + for (RenderView *rview = rr->views.first; rview; rview = rview->next) { + if (!view || STREQ(view, rview->name)) { + IMB_exr_add_view(exrhandle, rview->name); } } } - else { - for (nr = 0, rview = rr->views.first; rview; rview = rview->next, nr++) { - if (is_mono) { - if (!STREQ(view, rview->name)) { + + /* Compositing result. */ + if (rr->have_combined) { + for (RenderView *rview = rr->views.first; rview; rview = rview->next) { + if (!rview->rectf) { + continue; + } + + const char *viewname = rview->name; + if (view) { + if (!STREQ(view, viewname)) { continue; } - chan_view = ""; - } - else { - /* if rendered only one view, we treat as a a non-view render */ - chan_view = rview->name; + else { + viewname = ""; + } } - IMB_exr_add_view(exrhandle, rview->name); + /* Skip compositing if only a single other layer is requested. */ + if (!multi_layer && layer != 0) { + continue; + } - if (rview->rectf) { + for (int a = 0; a < 4; a++) { char passname[EXR_PASS_MAXNAME]; - for (a = 0; a < 4; a++) { - set_pass_name(passname, RE_PASSNAME_COMBINED, a, "RGBA"); - IMB_exr_add_channel(exrhandle, RE_PASSNAME_COMBINED, passname, - chan_view, 4, 4 * width, rview->rectf + a, - use_half_float); + char layname[EXR_PASS_MAXNAME]; + const char *chan_id = "RGBA"; + + if (multi_layer) { + set_pass_name(passname, "Combined", a, chan_id); + BLI_strncpy(layname, "Composite", sizeof(layname)); } + else { + passname[0] = chan_id[a]; + passname[1] = '\0'; + layname[0] = '\0'; + } + + IMB_exr_add_channel(exrhandle, layname, passname, viewname, + 4, 4 * rr->rectx, rview->rectf + a, half_float); + } + + if (write_z && rview->rectz) { + const char *layname = (multi_layer)? "Composite": ""; + IMB_exr_add_channel(exrhandle, layname, "Z", viewname, + 1, rr->rectx, rview->rectz, false); } } + } - /* add layers/passes and assign channels */ - for (rl = rr->layers.first; rl; rl = rl->next) { + /* Other render layers. */ + int nr = (rr->have_combined)? 1: 0; + for (RenderLayer *rl = rr->layers.first; rl; rl = rl->next, nr++) { + /* Skip other render layers if requested. */ + if (!multi_layer && nr != layer) { + continue; + } - /* passes are allocated in sync */ - for (rpass = rl->passes.first; rpass; rpass = rpass->next) { - const int xstride = rpass->channels; - char passname[EXR_PASS_MAXNAME]; + for (RenderPass *rp = rl->passes.first; rp; rp = rp->next) { + /* Skip non-RGBA and Z passes if not using multi layer. */ + if (!multi_layer && !(STREQ(rp->name, RE_PASSNAME_COMBINED) || + STREQ(rp->name, "") || + (STREQ(rp->name, RE_PASSNAME_Z) && write_z))) { + continue; + } - if (is_mono) { - if (!STREQ(view, rpass->view)) { - continue; - } - chan_view = ""; + /* Skip pass if it does not match the requested view(s). */ + const char *viewname = rp->view; + if (view) { + if (!STREQ(view, viewname)) { + continue; } else { - /* if rendered only one view, we treat as a a non-view render */ - chan_view = (nr > 1 ? rpass->view :""); + viewname = ""; } + } - for (a = 0; a < xstride; a++) { - set_pass_name(passname, rpass->name, a, rpass->chan_id); - IMB_exr_add_channel(exrhandle, rl->name, passname, chan_view, - xstride, xstride * width, rpass->rect + a, - STREQ(rpass->name, RE_PASSNAME_Z) ? false : use_half_float); + for (int a = 0; a < rp->channels; a++) { + /* Save Combined as RGBA if single layer save. */ + char passname[EXR_PASS_MAXNAME]; + char layname[EXR_PASS_MAXNAME]; + + if (multi_layer) { + set_pass_name(passname, rp->name, a, rp->chan_id); + BLI_strncpy(layname, rl->name, sizeof(layname)); + } + else { + passname[0] = rp->chan_id[a]; + passname[1] = '\0'; + layname[0] = '\0'; } + + /* Add channel. */ + IMB_exr_add_channel(exrhandle, layname, passname, viewname, + rp->channels, rp->channels * rr->rectx, rp->rect + a, + STREQ(rp->name, RE_PASSNAME_Z) ? false : half_float); } } } @@ -923,14 +952,14 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil BLI_make_existing_file(filename); - if (IMB_exr_begin_write(exrhandle, filename, width, height, compress, rr->stamp_data)) { + int compress = (imf ? imf->exr_codec : 0); + bool success = IMB_exr_begin_write(exrhandle, filename, rr->rectx, rr->recty, compress, rr->stamp_data); + if (success) { IMB_exr_write_channels(exrhandle); - success = true; } else { /* TODO, get the error from openexr's exception */ BKE_reportf(reports, RPT_ERROR, "Error writing render result, %s (see console)", strerror(errno)); - success = false; } IMB_exr_close(exrhandle); @@ -1245,7 +1274,7 @@ void render_result_exr_file_cache_write(Render *re) render_result_exr_file_cache_path(re->scene, root, str); printf("Caching exr file, %dx%d, %s\n", rr->rectx, rr->recty, str); - RE_WriteRenderResult(NULL, rr, str, NULL, true, NULL); + RE_WriteRenderResult(NULL, rr, str, NULL, NULL, -1); } /* For cache, makes exact copy of render result */ @@ -1370,7 +1399,7 @@ void render_result_rect_get_pixels(RenderResult *rr, unsigned int *rect, int rec /*************************** multiview functions *****************************/ -bool RE_HasFakeLayer(RenderResult *res) +bool RE_HasCombinedLayer(RenderResult *res) { RenderView *rv; diff --git a/source/creator/creator_signals.c b/source/creator/creator_signals.c index 80aba762cfc..81e6178c502 100644 --- a/source/creator/creator_signals.c +++ b/source/creator/creator_signals.c @@ -188,67 +188,67 @@ LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo) { switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: - fputs("Error: EXCEPTION_ACCESS_VIOLATION\n", stderr); + fputs("Error : EXCEPTION_ACCESS_VIOLATION\n", stderr); break; case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: - fputs("Error: EXCEPTION_ARRAY_BOUNDS_EXCEEDED\n", stderr); + fputs("Error : EXCEPTION_ARRAY_BOUNDS_EXCEEDED\n", stderr); break; case EXCEPTION_BREAKPOINT: - fputs("Error: EXCEPTION_BREAKPOINT\n", stderr); + fputs("Error : EXCEPTION_BREAKPOINT\n", stderr); break; case EXCEPTION_DATATYPE_MISALIGNMENT: - fputs("Error: EXCEPTION_DATATYPE_MISALIGNMENT\n", stderr); + fputs("Error : EXCEPTION_DATATYPE_MISALIGNMENT\n", stderr); break; case EXCEPTION_FLT_DENORMAL_OPERAND: - fputs("Error: EXCEPTION_FLT_DENORMAL_OPERAND\n", stderr); + fputs("Error : EXCEPTION_FLT_DENORMAL_OPERAND\n", stderr); break; case EXCEPTION_FLT_DIVIDE_BY_ZERO: - fputs("Error: EXCEPTION_FLT_DIVIDE_BY_ZERO\n", stderr); + fputs("Error : EXCEPTION_FLT_DIVIDE_BY_ZERO\n", stderr); break; case EXCEPTION_FLT_INEXACT_RESULT: - fputs("Error: EXCEPTION_FLT_INEXACT_RESULT\n", stderr); + fputs("Error : EXCEPTION_FLT_INEXACT_RESULT\n", stderr); break; case EXCEPTION_FLT_INVALID_OPERATION: - fputs("Error: EXCEPTION_FLT_INVALID_OPERATION\n", stderr); + fputs("Error : EXCEPTION_FLT_INVALID_OPERATION\n", stderr); break; case EXCEPTION_FLT_OVERFLOW: - fputs("Error: EXCEPTION_FLT_OVERFLOW\n", stderr); + fputs("Error : EXCEPTION_FLT_OVERFLOW\n", stderr); break; case EXCEPTION_FLT_STACK_CHECK: - fputs("Error: EXCEPTION_FLT_STACK_CHECK\n", stderr); + fputs("Error : EXCEPTION_FLT_STACK_CHECK\n", stderr); break; case EXCEPTION_FLT_UNDERFLOW: - fputs("Error: EXCEPTION_FLT_UNDERFLOW\n", stderr); + fputs("Error : EXCEPTION_FLT_UNDERFLOW\n", stderr); break; case EXCEPTION_ILLEGAL_INSTRUCTION: - fputs("Error: EXCEPTION_ILLEGAL_INSTRUCTION\n", stderr); + fputs("Error : EXCEPTION_ILLEGAL_INSTRUCTION\n", stderr); break; case EXCEPTION_IN_PAGE_ERROR: - fputs("Error: EXCEPTION_IN_PAGE_ERROR\n", stderr); + fputs("Error : EXCEPTION_IN_PAGE_ERROR\n", stderr); break; case EXCEPTION_INT_DIVIDE_BY_ZERO: - fputs("Error: EXCEPTION_INT_DIVIDE_BY_ZERO\n", stderr); + fputs("Error : EXCEPTION_INT_DIVIDE_BY_ZERO\n", stderr); break; case EXCEPTION_INT_OVERFLOW: - fputs("Error: EXCEPTION_INT_OVERFLOW\n", stderr); + fputs("Error : EXCEPTION_INT_OVERFLOW\n", stderr); break; case EXCEPTION_INVALID_DISPOSITION: - fputs("Error: EXCEPTION_INVALID_DISPOSITION\n", stderr); + fputs("Error : EXCEPTION_INVALID_DISPOSITION\n", stderr); break; case EXCEPTION_NONCONTINUABLE_EXCEPTION: - fputs("Error: EXCEPTION_NONCONTINUABLE_EXCEPTION\n", stderr); + fputs("Error : EXCEPTION_NONCONTINUABLE_EXCEPTION\n", stderr); break; case EXCEPTION_PRIV_INSTRUCTION: - fputs("Error: EXCEPTION_PRIV_INSTRUCTION\n", stderr); + fputs("Error : EXCEPTION_PRIV_INSTRUCTION\n", stderr); break; case EXCEPTION_SINGLE_STEP: - fputs("Error: EXCEPTION_SINGLE_STEP\n", stderr); + fputs("Error : EXCEPTION_SINGLE_STEP\n", stderr); break; case EXCEPTION_STACK_OVERFLOW: - fputs("Error: EXCEPTION_STACK_OVERFLOW\n", stderr); + fputs("Error : EXCEPTION_STACK_OVERFLOW\n", stderr); break; default: - fputs("Error: Unrecognized Exception\n", stderr); + fputs("Error : Unrecognized Exception\n", stderr); break; } @@ -257,6 +257,19 @@ LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo) /* If this is a stack overflow then we can't walk the stack, so just show * where the error happened */ if (EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode) { + HMODULE mod; + CHAR modulename[MAX_PATH]; + LPVOID address = ExceptionInfo->ExceptionRecord->ExceptionAddress; + + fprintf(stderr, "Address : 0x%p\n", address); + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, address, &mod)) { + if (GetModuleFileName(mod, modulename, MAX_PATH)) { + fprintf(stderr, "Module : %s\n", modulename); + } + } + + fflush(stderr); + #ifdef NDEBUG TerminateProcess(GetCurrentProcess(), SIGSEGV); #else |