Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2017-11-08 02:20:59 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2017-11-08 02:20:59 +0300
commit7b1d7074817dac9d0f088e8e7e5b336bae662c36 (patch)
tree4ebd67459d2fc160d3a6c76a2509cefc68f4e89c /source/blender
parent1b18e158025a488e1ba2446ad93c2eb563c11611 (diff)
parenta0478ebe379c8384376586e2880ebc813a6afef7 (diff)
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_node.h1
-rw-r--r--source/blender/blenkernel/intern/image.c120
-rw-r--r--source/blender/blenkernel/intern/node.c1
-rw-r--r--source/blender/editors/space_image/image_buttons.c54
-rw-r--r--source/blender/editors/space_image/image_ops.c33
-rw-r--r--source/blender/editors/space_node/drawnode.c8
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl5
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp477
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_multi.h13
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_stub.cpp18
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c10
-rw-r--r--source/blender/nodes/CMakeLists.txt1
-rw-r--r--source/blender/nodes/NOD_shader.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bevel.c70
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h5
-rw-r--r--source/blender/render/intern/include/render_result.h1
-rw-r--r--source/blender/render/intern/source/pipeline.c64
-rw-r--r--source/blender/render/intern/source/render_result.c183
19 files changed, 414 insertions, 652 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;