/* called from within UI, saves both rendered result as a file-read result */ int RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, int compress) { RenderLayer *rl; RenderPass *rpass; void *exrhandle = IMB_exr_get_handle(); int success; BLI_make_existing_file(filename); /* composite result */ if (rr->rectf) { IMB_exr_add_channel(exrhandle, "Composite", "Combined.R", 4, 4 * rr->rectx, rr->rectf); IMB_exr_add_channel(exrhandle, "Composite", "Combined.G", 4, 4 * rr->rectx, rr->rectf + 1); IMB_exr_add_channel(exrhandle, "Composite", "Combined.B", 4, 4 * rr->rectx, rr->rectf + 2); IMB_exr_add_channel(exrhandle, "Composite", "Combined.A", 4, 4 * rr->rectx, rr->rectf + 3); } /* add layers/passes and assign channels */ for (rl = rr->layers.first; rl; rl = rl->next) { /* combined */ if (rl->rectf) { int a, xstride = 4; for (a = 0; a < xstride; a++) { IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), xstride, xstride * rr->rectx, rl->rectf + a); } } /* passes are allocated in sync */ for (rpass = rl->passes.first; rpass; rpass = rpass->next) { int a, xstride = rpass->channels; for (a = 0; a < xstride; a++) { if (rpass->passtype) { IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), xstride, xstride * rr->rectx, rpass->rect + a); } else { IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), xstride, xstride * rr->rectx, rpass->rect + a); } } } } /* when the filename has no permissions, this can fail */ if (IMB_exr_begin_write(exrhandle, filename, rr->rectx, rr->recty, compress)) { IMB_exr_write_channels(exrhandle); success = TRUE; } else { /* TODO, get the error from openexr's exception */ BKE_report(reports, RPT_ERROR, "Error writing render result (see console)"); success = FALSE; } IMB_exr_close(exrhandle); return success; }
/* called for reading temp files, and for external engines */ int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, const char *filepath) { RenderLayer *rl; RenderPass *rpass; void *exrhandle = IMB_exr_get_handle(); int rectx, recty; if (IMB_exr_begin_read(exrhandle, filepath, &rectx, &recty) == 0) { printf("failed being read %s\n", filepath); IMB_exr_close(exrhandle); return 0; } if (rr == NULL || rectx != rr->rectx || recty != rr->recty) { if (rr) printf("error in reading render result: dimensions don't match\n"); else printf("error in reading render result: NULL result pointer\n"); IMB_exr_close(exrhandle); return 0; } for (rl = rr->layers.first; rl; rl = rl->next) { if (rl_single && rl_single != rl) continue; /* combined */ if (rl->rectf) { int a, xstride = 4; for (a = 0; a < xstride; a++) IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), xstride, xstride * rectx, rl->rectf + a); } /* passes are allocated in sync */ for (rpass = rl->passes.first; rpass; rpass = rpass->next) { int a, xstride = rpass->channels; for (a = 0; a < xstride; a++) IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), xstride, xstride * rectx, rpass->rect + a); BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name)); } } IMB_exr_read_channels(exrhandle); IMB_exr_close(exrhandle); return 1; }
/* called for reading temp files, and for external engines */ int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, const char *filepath) { RenderLayer *rl; RenderPass *rpass; void *exrhandle = IMB_exr_get_handle(); int rectx, recty; if (IMB_exr_begin_read(exrhandle, filepath, &rectx, &recty) == 0) { printf("failed being read %s\n", filepath); IMB_exr_close(exrhandle); return 0; } if (rr == NULL || rectx != rr->rectx || recty != rr->recty) { if (rr) printf("error in reading render result: dimensions don't match\n"); else printf("error in reading render result: NULL result pointer\n"); IMB_exr_close(exrhandle); return 0; } for (rl = rr->layers.first; rl; rl = rl->next) { if (rl_single && rl_single != rl) continue; /* passes are allocated in sync */ for (rpass = rl->passes.first; rpass; rpass = rpass->next) { const int xstride = rpass->channels; int a; char passname[EXR_PASS_MAXNAME]; for (a = 0; a < xstride; a++) { set_pass_name(passname, rpass->passtype, a, rpass->view); IMB_exr_set_channel(exrhandle, rl->name, passname, xstride, xstride * rectx, rpass->rect + a); } set_pass_name(rpass->name, rpass->passtype, -1, rpass->view); } } IMB_exr_read_channels(exrhandle); IMB_exr_close(exrhandle); return 1; }
void OutputOpenExrMultiLayerOperation::deinitExecution() { unsigned int width = this->getWidth(); unsigned int height = this->getHeight(); if (width != 0 && height != 0) { Main *bmain = G.main; /* TODO, have this passed along */ char filename[FILE_MAX]; void *exrhandle = IMB_exr_get_handle(); BKE_makepicstring_from_type(filename, this->m_path, bmain->name, this->m_rd->cfra, R_IMF_IMTYPE_MULTILAYER, (this->m_rd->scemode & R_EXTENSION), true); BLI_make_existing_file(filename); for (unsigned int i = 0; i < this->m_layers.size(); ++i) { OutputOpenExrLayer &layer = this->m_layers[i]; if (!layer.imageInput) continue; /* skip unconnected sockets */ char channelname[EXR_TOT_MAXNAME]; BLI_strncpy(channelname, this->m_layers[i].name, sizeof(channelname) - 2); char *channelname_ext = channelname + strlen(channelname); float *buf = this->m_layers[i].outputBuffer; /* create channels */ switch (this->m_layers[i].datatype) { case COM_DT_VALUE: strcpy(channelname_ext, ".V"); IMB_exr_add_channel(exrhandle, 0, channelname, 1, width, buf); break; case COM_DT_VECTOR: strcpy(channelname_ext, ".X"); IMB_exr_add_channel(exrhandle, 0, channelname, 3, 3 * width, buf); strcpy(channelname_ext, ".Y"); IMB_exr_add_channel(exrhandle, 0, channelname, 3, 3 * width, buf + 1); strcpy(channelname_ext, ".Z"); IMB_exr_add_channel(exrhandle, 0, channelname, 3, 3 * width, buf + 2); break; case COM_DT_COLOR: strcpy(channelname_ext, ".R"); IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf); strcpy(channelname_ext, ".G"); IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf + 1); strcpy(channelname_ext, ".B"); IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf + 2); strcpy(channelname_ext, ".A"); IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf + 3); break; default: break; } } /* when the filename has no permissions, this can fail */ if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec)) { IMB_exr_write_channels(exrhandle); } else { /* TODO, get the error from openexr's exception */ /* XXX nice way to do report? */ printf("Error Writing Render Result, see console\n"); } IMB_exr_close(exrhandle); for (unsigned int i = 0; i < this->m_layers.size(); ++i) { if (this->m_layers[i].outputBuffer) { MEM_freeN(this->m_layers[i].outputBuffer); this->m_layers[i].outputBuffer = NULL; } this->m_layers[i].imageInput = NULL; } } }
/* re->winx,winy is coordinate space of entire image, partrct the part within */ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuffers, const char *layername, const char *viewname) { RenderResult *rr; RenderLayer *rl; RenderView *rv; SceneRenderLayer *srl; int rectx, recty; int nr; rectx = BLI_rcti_size_x(partrct); recty = BLI_rcti_size_y(partrct); if (rectx <= 0 || recty <= 0) return NULL; rr = MEM_callocN(sizeof(RenderResult), "new render result"); rr->rectx = rectx; rr->recty = recty; rr->renrect.xmin = 0; rr->renrect.xmax = rectx - 2 * crop; /* crop is one or two extra pixels rendered for filtering, is used for merging and display too */ rr->crop = crop; /* tilerect is relative coordinates within render disprect. do not subtract crop yet */ rr->tilerect.xmin = partrct->xmin - re->disprect.xmin; rr->tilerect.xmax = partrct->xmax - re->disprect.xmin; rr->tilerect.ymin = partrct->ymin - re->disprect.ymin; rr->tilerect.ymax = partrct->ymax - re->disprect.ymin; if (savebuffers) { rr->do_exr_tile = true; } render_result_views_new(rr, &re->r); /* check renderdata for amount of layers */ for (nr = 0, srl = re->r.layers.first; srl; srl = srl->next, nr++) { if (layername && layername[0]) if (!STREQ(srl->name, layername)) continue; if (re->r.scemode & R_SINGLE_LAYER) { if (nr != re->r.actlay) continue; } else { if (srl->layflag & SCE_LAY_DISABLE) continue; } rl = MEM_callocN(sizeof(RenderLayer), "new render layer"); BLI_addtail(&rr->layers, rl); BLI_strncpy(rl->name, srl->name, sizeof(rl->name)); rl->lay = srl->lay; rl->lay_zmask = srl->lay_zmask; rl->lay_exclude = srl->lay_exclude; rl->layflag = srl->layflag; rl->passflag = srl->passflag; /* for debugging: srl->passflag | SCE_PASS_RAYHITS; */ rl->pass_xor = srl->pass_xor; rl->light_override = srl->light_override; rl->mat_override = srl->mat_override; rl->rectx = rectx; rl->recty = recty; if (rr->do_exr_tile) { rl->display_buffer = MEM_mapallocN(rectx * recty * sizeof(unsigned int), "Combined display space rgba"); rl->exrhandle = IMB_exr_get_handle(); } for (rv = rr->views.first; rv; rv = rv->next) { const char *view = rv->name; if (viewname && viewname[0]) if (!STREQ(view, viewname)) continue; if (rr->do_exr_tile) IMB_exr_add_view(rl->exrhandle, view); /* a renderlayer should always have a Combined pass*/ render_layer_add_pass(rr, rl, 4, SCE_PASS_COMBINED, view); if (srl->passflag & SCE_PASS_Z) render_layer_add_pass(rr, rl, 1, SCE_PASS_Z, view); if (srl->passflag & SCE_PASS_VECTOR) render_layer_add_pass(rr, rl, 4, SCE_PASS_VECTOR, view); if (srl->passflag & SCE_PASS_NORMAL) render_layer_add_pass(rr, rl, 3, SCE_PASS_NORMAL, view); if (srl->passflag & SCE_PASS_UV) render_layer_add_pass(rr, rl, 3, SCE_PASS_UV, view); if (srl->passflag & SCE_PASS_RGBA) render_layer_add_pass(rr, rl, 4, SCE_PASS_RGBA, view); if (srl->passflag & SCE_PASS_EMIT) render_layer_add_pass(rr, rl, 3, SCE_PASS_EMIT, view); if (srl->passflag & SCE_PASS_DIFFUSE) render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE, view); if (srl->passflag & SCE_PASS_SPEC) render_layer_add_pass(rr, rl, 3, SCE_PASS_SPEC, view); if (srl->passflag & SCE_PASS_AO) render_layer_add_pass(rr, rl, 3, SCE_PASS_AO, view); if (srl->passflag & SCE_PASS_ENVIRONMENT) render_layer_add_pass(rr, rl, 3, SCE_PASS_ENVIRONMENT, view); if (srl->passflag & SCE_PASS_INDIRECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_INDIRECT, view); if (srl->passflag & SCE_PASS_SHADOW) render_layer_add_pass(rr, rl, 3, SCE_PASS_SHADOW, view); if (srl->passflag & SCE_PASS_REFLECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_REFLECT, view); if (srl->passflag & SCE_PASS_REFRACT) render_layer_add_pass(rr, rl, 3, SCE_PASS_REFRACT, view); if (srl->passflag & SCE_PASS_INDEXOB) render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB, view); if (srl->passflag & SCE_PASS_INDEXMA) render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXMA, view); if (srl->passflag & SCE_PASS_MIST) render_layer_add_pass(rr, rl, 1, SCE_PASS_MIST, view); if (rl->passflag & SCE_PASS_RAYHITS) render_layer_add_pass(rr, rl, 4, SCE_PASS_RAYHITS, view); if (srl->passflag & SCE_PASS_DIFFUSE_DIRECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_DIRECT, view); if (srl->passflag & SCE_PASS_DIFFUSE_INDIRECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_INDIRECT, view); if (srl->passflag & SCE_PASS_DIFFUSE_COLOR) render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_COLOR, view); if (srl->passflag & SCE_PASS_GLOSSY_DIRECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_DIRECT, view); if (srl->passflag & SCE_PASS_GLOSSY_INDIRECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_INDIRECT, view); if (srl->passflag & SCE_PASS_GLOSSY_COLOR) render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_COLOR, view); if (srl->passflag & SCE_PASS_TRANSM_DIRECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_DIRECT, view); if (srl->passflag & SCE_PASS_TRANSM_INDIRECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_INDIRECT, view); if (srl->passflag & SCE_PASS_TRANSM_COLOR) render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_COLOR, view); if (srl->passflag & SCE_PASS_SUBSURFACE_DIRECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_DIRECT, view); if (srl->passflag & SCE_PASS_SUBSURFACE_INDIRECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_INDIRECT, view); if (srl->passflag & SCE_PASS_SUBSURFACE_COLOR) render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_COLOR, view); #ifdef WITH_CYCLES_DEBUG if (BKE_scene_use_new_shading_nodes(re->scene)) { render_layer_add_debug_pass(rr, rl, 1, SCE_PASS_DEBUG, re->r.debug_pass_type, view); } #endif } } /* sss, previewrender and envmap don't do layers, so we make a default one */ if (BLI_listbase_is_empty(&rr->layers) && !(layername && layername[0])) { rl = MEM_callocN(sizeof(RenderLayer), "new render layer"); BLI_addtail(&rr->layers, rl); rl->rectx = rectx; rl->recty = recty; /* duplicate code... */ if (rr->do_exr_tile) { rl->display_buffer = MEM_mapallocN(rectx * recty * sizeof(unsigned int), "Combined display space rgba"); rl->exrhandle = IMB_exr_get_handle(); } for (rv = rr->views.first; rv; rv = rv->next) { const char *view = rv->name; if (viewname && viewname[0]) if (strcmp(view, viewname) != 0) continue; if (rr->do_exr_tile) IMB_exr_add_view(rl->exrhandle, view); /* a renderlayer should always have a Combined pass */ render_layer_add_pass(rr, rl, 4, SCE_PASS_COMBINED, view); } /* note, this has to be in sync with scene.c */ rl->lay = (1 << 20) - 1; rl->layflag = 0x7FFF; /* solid ztra halo strand */ rl->passflag = SCE_PASS_COMBINED; re->r.actlay = 0; } /* border render; calculate offset for use in compositor. compo is centralized coords */ /* XXX obsolete? I now use it for drawing border render offset (ton) */ rr->xof = re->disprect.xmin + BLI_rcti_cent_x(&re->disprect) - (re->winx / 2); rr->yof = re->disprect.ymin + BLI_rcti_cent_y(&re->disprect) - (re->winy / 2); return rr; }
/* 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) { 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; 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); 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++) { if (is_mono) { if (!STREQ(view, rview->name)) { 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); if (rview->rectf) { for (a = 0; a < 4; a++) { IMB_exr_add_channel(exrhandle, "Composite", name_from_passtype(SCE_PASS_COMBINED, a), chan_view, 4, 4 * width, rview->rectf + a, use_half_float); } } } /* add layers/passes and assign channels */ for (rl = rr->layers.first; rl; rl = rl->next) { /* passes are allocated in sync */ for (rpass = rl->passes.first; rpass; rpass = rpass->next) { const int xstride = rpass->channels; if (is_mono) { if (!STREQ(view, rpass->view)) { continue; } chan_view = ""; } else { /* if rendered only one view, we treat as a a non-view render */ chan_view = (nr > 1 ? rpass->view :""); } for (a = 0; a < xstride; a++) { if (rpass->passtype) { IMB_exr_add_channel(exrhandle, rl->name, name_from_passtype(rpass->passtype, a), chan_view, xstride, xstride * width, rpass->rect + a, rpass->passtype == SCE_PASS_Z ? false : use_half_float); } else { IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), chan_view, xstride, xstride * width, rpass->rect + a, use_half_float); } } } } } BLI_make_existing_file(filename); if (IMB_exr_begin_write(exrhandle, filename, width, height, compress, rr->stamp_data)) { IMB_exr_write_channels(exrhandle); success = true; } else { /* TODO, get the error from openexr's exception */ BKE_report(reports, RPT_ERROR, "Error writing render result (see console)"); success = false; } IMB_exr_close(exrhandle); return success; }
/* write input data into layers */ static void exec_output_file_multilayer(RenderData *rd, bNode *node, bNodeStack **in) { Main *bmain= G.main; /* TODO, have this passed along */ NodeImageMultiFile *nimf= node->storage; void *exrhandle= IMB_exr_get_handle(); char filename[FILE_MAX]; bNodeSocket *sock; int i; /* Must have consistent pixel size for exr file, simply take the first valid input size. */ int rectx = -1; int recty = -1; int has_preview = 0; BKE_makepicstring(filename, nimf->base_path, bmain->name, rd->cfra, R_IMF_IMTYPE_MULTILAYER, (rd->scemode & R_EXTENSION), TRUE); BLI_make_existing_file(filename); for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) { if (in[i]->data) { NodeImageMultiFileSocket *sockdata = sock->storage; CompBuf *cbuf = in[i]->data; char channelname[EXR_TOT_MAXNAME]; /* '.' and single character channel name is appended */ char *channelname_ext; if (cbuf->rect_procedural) { printf("Error writing multilayer EXR: Procedural buffer not supported\n"); continue; } if (rectx < 0) { rectx = cbuf->x; recty = cbuf->y; } else if (cbuf->x != rectx || cbuf->y != recty) { printf("Error: Multilayer EXR output node %s expects same resolution for all input buffers. Layer %s skipped.\n", node->name, sock->name); continue; } BLI_strncpy(channelname, sockdata->layer, sizeof(channelname)-2); channelname_ext = channelname + strlen(channelname); /* create channels */ switch (cbuf->type) { case CB_VAL: strcpy(channelname_ext, ".V"); IMB_exr_add_channel(exrhandle, NULL, channelname, 1, rectx, cbuf->rect); break; case CB_VEC2: strcpy(channelname_ext, ".X"); IMB_exr_add_channel(exrhandle, NULL, channelname, 2, 2*rectx, cbuf->rect); strcpy(channelname_ext, ".Y"); IMB_exr_add_channel(exrhandle, NULL, channelname, 2, 2*rectx, cbuf->rect+1); break; case CB_VEC3: strcpy(channelname_ext, ".X"); IMB_exr_add_channel(exrhandle, NULL, channelname, 3, 3*rectx, cbuf->rect); strcpy(channelname_ext, ".Y"); IMB_exr_add_channel(exrhandle, NULL, channelname, 3, 3*rectx, cbuf->rect+1); strcpy(channelname_ext, ".Z"); IMB_exr_add_channel(exrhandle, NULL, channelname, 3, 3*rectx, cbuf->rect+2); break; case CB_RGBA: strcpy(channelname_ext, ".R"); IMB_exr_add_channel(exrhandle, NULL, channelname, 4, 4*rectx, cbuf->rect); strcpy(channelname_ext, ".G"); IMB_exr_add_channel(exrhandle, NULL, channelname, 4, 4*rectx, cbuf->rect+1); strcpy(channelname_ext, ".B"); IMB_exr_add_channel(exrhandle, NULL, channelname, 4, 4*rectx, cbuf->rect+2); strcpy(channelname_ext, ".A"); IMB_exr_add_channel(exrhandle, NULL, channelname, 4, 4*rectx, cbuf->rect+3); break; } /* simply pick the first valid input for preview */ if (!has_preview) { generate_preview(rd, node, cbuf); has_preview = 1; } } } /* when the filename has no permissions, this can fail */ if (IMB_exr_begin_write(exrhandle, filename, rectx, recty, nimf->format.exr_codec)) { IMB_exr_write_channels(exrhandle); } else { /* TODO, get the error from openexr's exception */ /* XXX nice way to do report? */ printf("Error Writing Render Result, see console\n"); } IMB_exr_close(exrhandle); }
/* re->winx,winy is coordinate space of entire image, partrct the part within */ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuffers, const char *layername) { RenderResult *rr; RenderLayer *rl; SceneRenderLayer *srl; int rectx, recty, nr; rectx = BLI_rcti_size_x(partrct); recty = BLI_rcti_size_y(partrct); if (rectx <= 0 || recty <= 0) return NULL; rr = MEM_callocN(sizeof(RenderResult), "new render result"); rr->rectx = rectx; rr->recty = recty; rr->renrect.xmin = 0; rr->renrect.xmax = rectx - 2 * crop; /* crop is one or two extra pixels rendered for filtering, is used for merging and display too */ rr->crop = crop; /* tilerect is relative coordinates within render disprect. do not subtract crop yet */ rr->tilerect.xmin = partrct->xmin - re->disprect.xmin; rr->tilerect.xmax = partrct->xmax - re->disprect.xmin; rr->tilerect.ymin = partrct->ymin - re->disprect.ymin; rr->tilerect.ymax = partrct->ymax - re->disprect.ymin; if (savebuffers) { rr->do_exr_tile = TRUE; } /* check renderdata for amount of layers */ for (nr = 0, srl = re->r.layers.first; srl; srl = srl->next, nr++) { if (layername && layername[0]) if (strcmp(srl->name, layername) != 0) continue; if ((re->r.scemode & R_SINGLE_LAYER) && nr != re->r.actlay) continue; if (srl->layflag & SCE_LAY_DISABLE) continue; rl = MEM_callocN(sizeof(RenderLayer), "new render layer"); BLI_addtail(&rr->layers, rl); BLI_strncpy(rl->name, srl->name, sizeof(rl->name)); rl->lay = srl->lay; rl->lay_zmask = srl->lay_zmask; rl->lay_exclude = srl->lay_exclude; rl->layflag = srl->layflag; rl->passflag = srl->passflag; /* for debugging: srl->passflag | SCE_PASS_RAYHITS; */ rl->pass_xor = srl->pass_xor; rl->light_override = srl->light_override; rl->mat_override = srl->mat_override; rl->rectx = rectx; rl->recty = recty; if (rr->do_exr_tile) { rl->exrhandle = IMB_exr_get_handle(); IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.R", 0, 0, NULL); IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.G", 0, 0, NULL); IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.B", 0, 0, NULL); IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.A", 0, 0, NULL); } else rl->rectf = MEM_mapallocN(rectx * recty * sizeof(float) * 4, "Combined rgba"); if (srl->passflag & SCE_PASS_Z) render_layer_add_pass(rr, rl, 1, SCE_PASS_Z); if (srl->passflag & SCE_PASS_VECTOR) render_layer_add_pass(rr, rl, 4, SCE_PASS_VECTOR); if (srl->passflag & SCE_PASS_NORMAL) render_layer_add_pass(rr, rl, 3, SCE_PASS_NORMAL); if (srl->passflag & SCE_PASS_UV) render_layer_add_pass(rr, rl, 3, SCE_PASS_UV); if (srl->passflag & SCE_PASS_RGBA) render_layer_add_pass(rr, rl, 4, SCE_PASS_RGBA); if (srl->passflag & SCE_PASS_EMIT) render_layer_add_pass(rr, rl, 3, SCE_PASS_EMIT); if (srl->passflag & SCE_PASS_DIFFUSE) render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE); if (srl->passflag & SCE_PASS_SPEC) render_layer_add_pass(rr, rl, 3, SCE_PASS_SPEC); if (srl->passflag & SCE_PASS_AO) render_layer_add_pass(rr, rl, 3, SCE_PASS_AO); if (srl->passflag & SCE_PASS_ENVIRONMENT) render_layer_add_pass(rr, rl, 3, SCE_PASS_ENVIRONMENT); if (srl->passflag & SCE_PASS_INDIRECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_INDIRECT); if (srl->passflag & SCE_PASS_SHADOW) render_layer_add_pass(rr, rl, 3, SCE_PASS_SHADOW); if (srl->passflag & SCE_PASS_REFLECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_REFLECT); if (srl->passflag & SCE_PASS_REFRACT) render_layer_add_pass(rr, rl, 3, SCE_PASS_REFRACT); if (srl->passflag & SCE_PASS_INDEXOB) render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB); if (srl->passflag & SCE_PASS_INDEXMA) render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXMA); if (srl->passflag & SCE_PASS_MIST) render_layer_add_pass(rr, rl, 1, SCE_PASS_MIST); if (rl->passflag & SCE_PASS_RAYHITS) render_layer_add_pass(rr, rl, 4, SCE_PASS_RAYHITS); if (srl->passflag & SCE_PASS_DIFFUSE_DIRECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_DIRECT); if (srl->passflag & SCE_PASS_DIFFUSE_INDIRECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_INDIRECT); if (srl->passflag & SCE_PASS_DIFFUSE_COLOR) render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_COLOR); if (srl->passflag & SCE_PASS_GLOSSY_DIRECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_DIRECT); if (srl->passflag & SCE_PASS_GLOSSY_INDIRECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_INDIRECT); if (srl->passflag & SCE_PASS_GLOSSY_COLOR) render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_COLOR); if (srl->passflag & SCE_PASS_TRANSM_DIRECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_DIRECT); if (srl->passflag & SCE_PASS_TRANSM_INDIRECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_INDIRECT); if (srl->passflag & SCE_PASS_TRANSM_COLOR) render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_COLOR); if (srl->passflag & SCE_PASS_SUBSURFACE_DIRECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_DIRECT); if (srl->passflag & SCE_PASS_SUBSURFACE_INDIRECT) render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_INDIRECT); if (srl->passflag & SCE_PASS_SUBSURFACE_COLOR) render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_COLOR); } /* sss, previewrender and envmap don't do layers, so we make a default one */ if (rr->layers.first == NULL && !(layername && layername[0])) { rl = MEM_callocN(sizeof(RenderLayer), "new render layer"); BLI_addtail(&rr->layers, rl); rl->rectx = rectx; rl->recty = recty; /* duplicate code... */ if (rr->do_exr_tile) { rl->exrhandle = IMB_exr_get_handle(); IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.R", 0, 0, NULL); IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.G", 0, 0, NULL); IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.B", 0, 0, NULL); IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.A", 0, 0, NULL); } else { rl->rectf = MEM_mapallocN(rectx * recty * sizeof(float) * 4, "Combined rgba"); } /* note, this has to be in sync with scene.c */ rl->lay = (1 << 20) - 1; rl->layflag = 0x7FFF; /* solid ztra halo strand */ rl->passflag = SCE_PASS_COMBINED; re->r.actlay = 0; } /* border render; calculate offset for use in compositor. compo is centralized coords */ /* XXX obsolete? I now use it for drawing border render offset (ton) */ rr->xof = re->disprect.xmin + BLI_rcti_cent_x(&re->disprect) - (re->winx / 2); rr->yof = re->disprect.ymin + BLI_rcti_cent_y(&re->disprect) - (re->winy / 2); return rr; }