Changeset View
Changeset View
Standalone View
Standalone View
source/blender/render/intern/source/render_result.c
| Show First 20 Lines • Show All 579 Lines • ▼ Show 20 Lines | |||||
| /* callbacks for render_result_new_from_exr */ | /* callbacks for render_result_new_from_exr */ | ||||
| static void *ml_addlayer_cb(void *base, const char *str) | static void *ml_addlayer_cb(void *base, const char *str) | ||||
| { | { | ||||
| RenderResult *rr = base; | RenderResult *rr = base; | ||||
| RenderLayer *rl; | RenderLayer *rl; | ||||
| rl = MEM_callocN(sizeof(RenderLayer), "new render layer"); | rl = MEM_callocN(sizeof(RenderLayer), "new render layer"); | ||||
| BLI_addtail(&rr->layers, rl); | BLI_addtail(&rr->layers, rl); | ||||
| BLI_strncpy(rl->name, str, EXR_LAY_MAXNAME); | BLI_strncpy(rl->name, str, EXR_LAY_MAXNAME); | ||||
| return rl; | return rl; | ||||
| } | } | ||||
| static void ml_addpass_cb(void *base, void *lay, const char *name, float *rect, int totchan, const char *chan_id, const char *view) | static void ml_addpass_cb(void *base, void *lay, const char *name, float *rect, int totchan, const char *chan_id, const char *view) | ||||
| { | { | ||||
| RenderResult *rr = base; | RenderResult *rr = base; | ||||
| RenderLayer *rl = lay; | RenderLayer *rl = lay; | ||||
| ▲ Show 20 Lines • Show All 154 Lines • ▼ Show 20 Lines | void render_result_views_new(RenderResult *rr, RenderData *rd) | ||||
| } | } | ||||
| /* we always need at least one view */ | /* we always need at least one view */ | ||||
| if (BLI_listbase_count_ex(&rr->views, 1) == 0) { | if (BLI_listbase_count_ex(&rr->views, 1) == 0) { | ||||
| render_result_view_new(rr, ""); | render_result_view_new(rr, ""); | ||||
| } | } | ||||
| } | } | ||||
| bool render_result_has_views(RenderResult *rr) | |||||
| { | |||||
| RenderView *rv = rr->views.first; | |||||
| return (rv && (rv->next || rv->name[0])); | |||||
| } | |||||
| /*********************************** Merge ***********************************/ | /*********************************** Merge ***********************************/ | ||||
| static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize) | static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize) | ||||
| { | { | ||||
| int y, tilex, tiley; | int y, tilex, tiley; | ||||
| size_t ofs, copylen; | size_t ofs, copylen; | ||||
| copylen = tilex = rrpart->rectx; | copylen = tilex = rrpart->rectx; | ||||
| ▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | if (rlp) { | ||||
| /* manually get next render pass */ | /* manually get next render pass */ | ||||
| rpassp = rpassp->next; | rpassp = rpassp->next; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* called from within UI and render pipeline, saves both rendered result as a file-read result | /* Called from the UI and render pipeline, to save multilayer and multiview | ||||
| * if multiview is true saves all views in a multiview exr | * images, optionally isolating a specific, view, layer or RGBA/Z pass. */ | ||||
| * else if view is not NULL saves single view | bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, ImageFormatData *imf, const char *view, const int layer) | ||||
| * else saves stereo3d | |||||
| */ | |||||
| bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, ImageFormatData *imf, const bool multiview, const char *view) | |||||
| { | { | ||||
| RenderLayer *rl; | |||||
| RenderPass *rpass; | |||||
| RenderView *rview; | |||||
| void *exrhandle = IMB_exr_get_handle(); | void *exrhandle = IMB_exr_get_handle(); | ||||
| bool success; | const bool half_float = (imf && imf->depth == R_IMF_CHAN_DEPTH_16); | ||||
| int a, nr; | const bool multi_layer = !(imf && imf->imtype == R_IMF_IMTYPE_OPENEXR); | ||||
| const char *chan_view = NULL; | |||||
| int compress = (imf ? imf->exr_codec : 0); | |||||
| size_t width, height; | |||||
dfelinto: -BLI_listbase_count
+BLI_listbase_count_ex(&rr->views, 2) | |||||
| const bool is_mono = view && !multiview; | if (render_result_has_views(rr)) { | ||||
| const bool use_half_float = (imf != NULL) ? (imf->depth == R_IMF_CHAN_DEPTH_16) : false; | /* First add views since IMB_exr_add_channel checks number of views. */ | ||||
| for (RenderView *rview = rr->views.first; rview; rview = rview->next) { | |||||
| width = rr->rectx; | if (!view || STREQ(view, rview->name)) { | ||||
| height = rr->recty; | |||||
| 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); | IMB_exr_add_view(exrhandle, rview->name); | ||||
| 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); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | |||||
| for (nr = 0, rview = rr->views.first; rview; rview = rview->next, nr++) { | for (RenderView *rview = rr->views.first; rview; rview = rview->next) { | ||||
| if (is_mono) { | int nr = 0; | ||||
| if (!STREQ(view, rview->name)) { | for (RenderLayer *rl = rr->layers.first; rl; rl = rl->next, nr++) { | ||||
| /* Skip other render layers if requested. */ | |||||
Not Done Inline Actions-if( +if ( dfelinto: `-if(` `+if (` | |||||
| if (!multi_layer && layer >= 0 && nr != layer) { | |||||
| continue; | continue; | ||||
| } | } | ||||
| chan_view = ""; | |||||
| } | |||||
| else { | |||||
| /* if rendered only one view, we treat as a a non-view render */ | |||||
| chan_view = rview->name; | |||||
| } | |||||
| IMB_exr_add_view(exrhandle, rview->name); | 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, RE_PASSNAME_Z) || | |||||
Not Done Inline Actionscode style: multi-line if should have "{" in a new line. And -if( +if (. dfelinto: code style: multi-line if should have "{" in a new line. And `-if(` `+if (`. | |||||
| STREQ(rp->name, ""))) { | |||||
| continue; | |||||
| } | |||||
| if (rview->rectf) { | /* Skip pass if it does not match the requested view(s). */ | ||||
| char passname[EXR_PASS_MAXNAME]; | const char *viewname = rp->view; | ||||
| for (a = 0; a < 4; a++) { | if(view) { | ||||
| set_pass_name(passname, RE_PASSNAME_COMBINED, a, "RGBA"); | if (STREQ(view, viewname)) { | ||||
| IMB_exr_add_channel(exrhandle, RE_PASSNAME_COMBINED, passname, | continue; | ||||
Not Done Inline Actions-if( +if ( dfelinto: `-if(` `+if (` | |||||
| chan_view, 4, 4 * width, rview->rectf + a, | |||||
| use_half_float); | |||||
| } | } | ||||
| else { | |||||
| viewname = ""; | |||||
| } | } | ||||
| } | } | ||||
| /* add layers/passes and assign channels */ | for (int a = 0; a < rp->channels; a++) { | ||||
| for (rl = rr->layers.first; rl; rl = rl->next) { | /* Save Combined as RGBA if single layer save. */ | ||||
| /* passes are allocated in sync */ | |||||
| for (rpass = rl->passes.first; rpass; rpass = rpass->next) { | |||||
| const int xstride = rpass->channels; | |||||
| char passname[EXR_PASS_MAXNAME]; | char passname[EXR_PASS_MAXNAME]; | ||||
| char layname[EXR_PASS_MAXNAME]; | |||||
| if (is_mono) { | if (multi_layer) { | ||||
| if (!STREQ(view, rpass->view)) { | set_pass_name(passname, rp->name, a, rp->chan_id); | ||||
| continue; | BLI_strncpy(layname, rl->name, sizeof(layname)); | ||||
| } | |||||
| chan_view = ""; | |||||
| } | } | ||||
| else { | else { | ||||
| /* if rendered only one view, we treat as a a non-view render */ | passname[0] = rp->chan_id[a]; | ||||
| chan_view = (nr > 1 ? rpass->view :""); | passname[1] = '\0'; | ||||
| layname[0] = '\0'; | |||||
| } | } | ||||
| for (a = 0; a < xstride; a++) { | /* Add channel. */ | ||||
| set_pass_name(passname, rpass->name, a, rpass->chan_id); | IMB_exr_add_channel(exrhandle, layname, passname, viewname, | ||||
| IMB_exr_add_channel(exrhandle, rl->name, passname, chan_view, | rp->channels, rp->channels * rr->rectx, rp->rect + a, | ||||
| xstride, xstride * width, rpass->rect + a, | STREQ(rp->name, RE_PASSNAME_Z) ? false : half_float); | ||||
| STREQ(rpass->name, RE_PASSNAME_Z) ? false : use_half_float); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| errno = 0; | errno = 0; | ||||
| BLI_make_existing_file(filename); | 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) { | |||||
Not Done Inline Actions-if( dfelinto: `-if(`
`+if (` | |||||
| IMB_exr_write_channels(exrhandle); | IMB_exr_write_channels(exrhandle); | ||||
| success = true; | |||||
| } | } | ||||
| else { | else { | ||||
| /* TODO, get the error from openexr's exception */ | /* TODO, get the error from openexr's exception */ | ||||
| BKE_reportf(reports, RPT_ERROR, "Error writing render result, %s (see console)", strerror(errno)); | BKE_reportf(reports, RPT_ERROR, "Error writing render result, %s (see console)", strerror(errno)); | ||||
| success = false; | |||||
| } | } | ||||
| IMB_exr_close(exrhandle); | IMB_exr_close(exrhandle); | ||||
| return success; | return success; | ||||
| } | } | ||||
| /**************************** Single Layer Rendering *************************/ | /**************************** Single Layer Rendering *************************/ | ||||
| ▲ Show 20 Lines • Show All 298 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| RenderResult *rr = re->result; | RenderResult *rr = re->result; | ||||
| char str[FILE_MAXFILE + FILE_MAXFILE + MAX_ID_NAME + 100]; | char str[FILE_MAXFILE + FILE_MAXFILE + MAX_ID_NAME + 100]; | ||||
| char *root = U.render_cachedir; | char *root = U.render_cachedir; | ||||
| render_result_exr_file_cache_path(re->scene, root, str); | render_result_exr_file_cache_path(re->scene, root, str); | ||||
| printf("Caching exr file, %dx%d, %s\n", rr->rectx, rr->recty, 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 */ | /* For cache, makes exact copy of render result */ | ||||
| bool render_result_exr_file_cache_read(Render *re) | bool render_result_exr_file_cache_read(Render *re) | ||||
| { | { | ||||
| char str[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100] = ""; | char str[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100] = ""; | ||||
| char *root = U.render_cachedir; | char *root = U.render_cachedir; | ||||
| ▲ Show 20 Lines • Show All 235 Lines • Show Last 20 Lines | |||||
-BLI_listbase_count
+BLI_listbase_count_ex(&rr->views, 2)