Blender V2.61 - r43446
|
00001 /* 00002 * 00003 * ***** BEGIN GPL LICENSE BLOCK ***** 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * as published by the Free Software Foundation; either version 2 00008 * of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software Foundation, 00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 * 00019 * The Original Code is Copyright (C) 2006 Blender Foundation. 00020 * All rights reserved. 00021 * 00022 * The Original Code is: all of this file. 00023 * 00024 * Contributor(s): none yet. 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00033 #include <stdio.h> 00034 #include <string.h> 00035 00036 #include "MEM_guardedalloc.h" 00037 00038 #include "BKE_image.h" 00039 #include "BKE_global.h" 00040 #include "BKE_main.h" 00041 #include "BKE_report.h" 00042 #include "BKE_utildefines.h" 00043 00044 #include "BLI_fileops.h" 00045 #include "BLI_listbase.h" 00046 #include "BLI_path_util.h" 00047 #include "BLI_string.h" 00048 #include "BLI_threads.h" 00049 #include "BLI_utildefines.h" 00050 00051 #include "IMB_imbuf.h" 00052 #include "IMB_imbuf_types.h" 00053 00054 #include "intern/openexr/openexr_multi.h" 00055 00056 #include "render_result.h" 00057 #include "render_types.h" 00058 00059 /********************************** Free *************************************/ 00060 00061 void render_result_free(RenderResult *res) 00062 { 00063 if(res==NULL) return; 00064 00065 while(res->layers.first) { 00066 RenderLayer *rl= res->layers.first; 00067 00068 if(rl->rectf) MEM_freeN(rl->rectf); 00069 /* acolrect and scolrect are optionally allocated in shade_tile, only free here since it can be used for drawing */ 00070 if(rl->acolrect) MEM_freeN(rl->acolrect); 00071 if(rl->scolrect) MEM_freeN(rl->scolrect); 00072 00073 while(rl->passes.first) { 00074 RenderPass *rpass= rl->passes.first; 00075 if(rpass->rect) MEM_freeN(rpass->rect); 00076 BLI_remlink(&rl->passes, rpass); 00077 MEM_freeN(rpass); 00078 } 00079 BLI_remlink(&res->layers, rl); 00080 MEM_freeN(rl); 00081 } 00082 00083 if(res->rect32) 00084 MEM_freeN(res->rect32); 00085 if(res->rectz) 00086 MEM_freeN(res->rectz); 00087 if(res->rectf) 00088 MEM_freeN(res->rectf); 00089 if(res->text) 00090 MEM_freeN(res->text); 00091 00092 MEM_freeN(res); 00093 } 00094 00095 /* version that's compatible with fullsample buffers */ 00096 void render_result_free_list(ListBase *lb, RenderResult *rr) 00097 { 00098 RenderResult *rrnext; 00099 00100 for(; rr; rr= rrnext) { 00101 rrnext= rr->next; 00102 00103 if(lb && lb->first) 00104 BLI_remlink(lb, rr); 00105 00106 render_result_free(rr); 00107 } 00108 } 00109 00110 /********************************* Names *************************************/ 00111 00112 /* NOTE: OpenEXR only supports 32 chars for layer+pass names 00113 In blender we now use max 10 chars for pass, max 20 for layer */ 00114 static const char *get_pass_name(int passtype, int channel) 00115 { 00116 00117 if(passtype == SCE_PASS_COMBINED) { 00118 if(channel==-1) return "Combined"; 00119 if(channel==0) return "Combined.R"; 00120 if(channel==1) return "Combined.G"; 00121 if(channel==2) return "Combined.B"; 00122 return "Combined.A"; 00123 } 00124 if(passtype == SCE_PASS_Z) { 00125 if(channel==-1) return "Depth"; 00126 return "Depth.Z"; 00127 } 00128 if(passtype == SCE_PASS_VECTOR) { 00129 if(channel==-1) return "Vector"; 00130 if(channel==0) return "Vector.X"; 00131 if(channel==1) return "Vector.Y"; 00132 if(channel==2) return "Vector.Z"; 00133 return "Vector.W"; 00134 } 00135 if(passtype == SCE_PASS_NORMAL) { 00136 if(channel==-1) return "Normal"; 00137 if(channel==0) return "Normal.X"; 00138 if(channel==1) return "Normal.Y"; 00139 return "Normal.Z"; 00140 } 00141 if(passtype == SCE_PASS_UV) { 00142 if(channel==-1) return "UV"; 00143 if(channel==0) return "UV.U"; 00144 if(channel==1) return "UV.V"; 00145 return "UV.A"; 00146 } 00147 if(passtype == SCE_PASS_RGBA) { 00148 if(channel==-1) return "Color"; 00149 if(channel==0) return "Color.R"; 00150 if(channel==1) return "Color.G"; 00151 if(channel==2) return "Color.B"; 00152 return "Color.A"; 00153 } 00154 if(passtype == SCE_PASS_EMIT) { 00155 if(channel==-1) return "Emit"; 00156 if(channel==0) return "Emit.R"; 00157 if(channel==1) return "Emit.G"; 00158 return "Emit.B"; 00159 } 00160 if(passtype == SCE_PASS_DIFFUSE) { 00161 if(channel==-1) return "Diffuse"; 00162 if(channel==0) return "Diffuse.R"; 00163 if(channel==1) return "Diffuse.G"; 00164 return "Diffuse.B"; 00165 } 00166 if(passtype == SCE_PASS_SPEC) { 00167 if(channel==-1) return "Spec"; 00168 if(channel==0) return "Spec.R"; 00169 if(channel==1) return "Spec.G"; 00170 return "Spec.B"; 00171 } 00172 if(passtype == SCE_PASS_SHADOW) { 00173 if(channel==-1) return "Shadow"; 00174 if(channel==0) return "Shadow.R"; 00175 if(channel==1) return "Shadow.G"; 00176 return "Shadow.B"; 00177 } 00178 if(passtype == SCE_PASS_AO) { 00179 if(channel==-1) return "AO"; 00180 if(channel==0) return "AO.R"; 00181 if(channel==1) return "AO.G"; 00182 return "AO.B"; 00183 } 00184 if(passtype == SCE_PASS_ENVIRONMENT) { 00185 if(channel==-1) return "Env"; 00186 if(channel==0) return "Env.R"; 00187 if(channel==1) return "Env.G"; 00188 return "Env.B"; 00189 } 00190 if(passtype == SCE_PASS_INDIRECT) { 00191 if(channel==-1) return "Indirect"; 00192 if(channel==0) return "Indirect.R"; 00193 if(channel==1) return "Indirect.G"; 00194 return "Indirect.B"; 00195 } 00196 if(passtype == SCE_PASS_REFLECT) { 00197 if(channel==-1) return "Reflect"; 00198 if(channel==0) return "Reflect.R"; 00199 if(channel==1) return "Reflect.G"; 00200 return "Reflect.B"; 00201 } 00202 if(passtype == SCE_PASS_REFRACT) { 00203 if(channel==-1) return "Refract"; 00204 if(channel==0) return "Refract.R"; 00205 if(channel==1) return "Refract.G"; 00206 return "Refract.B"; 00207 } 00208 if(passtype == SCE_PASS_INDEXOB) { 00209 if(channel==-1) return "IndexOB"; 00210 return "IndexOB.X"; 00211 } 00212 if(passtype == SCE_PASS_INDEXMA) { 00213 if(channel==-1) return "IndexMA"; 00214 return "IndexMA.X"; 00215 } 00216 if(passtype == SCE_PASS_MIST) { 00217 if(channel==-1) return "Mist"; 00218 return "Mist.Z"; 00219 } 00220 if(passtype == SCE_PASS_RAYHITS) 00221 { 00222 if(channel==-1) return "Rayhits"; 00223 if(channel==0) return "Rayhits.R"; 00224 if(channel==1) return "Rayhits.G"; 00225 return "Rayhits.B"; 00226 } 00227 return "Unknown"; 00228 } 00229 00230 static int passtype_from_name(const char *str) 00231 { 00232 00233 if(strcmp(str, "Combined")==0) 00234 return SCE_PASS_COMBINED; 00235 00236 if(strcmp(str, "Depth")==0) 00237 return SCE_PASS_Z; 00238 00239 if(strcmp(str, "Vector")==0) 00240 return SCE_PASS_VECTOR; 00241 00242 if(strcmp(str, "Normal")==0) 00243 return SCE_PASS_NORMAL; 00244 00245 if(strcmp(str, "UV")==0) 00246 return SCE_PASS_UV; 00247 00248 if(strcmp(str, "Color")==0) 00249 return SCE_PASS_RGBA; 00250 00251 if(strcmp(str, "Emit")==0) 00252 return SCE_PASS_EMIT; 00253 00254 if(strcmp(str, "Diffuse")==0) 00255 return SCE_PASS_DIFFUSE; 00256 00257 if(strcmp(str, "Spec")==0) 00258 return SCE_PASS_SPEC; 00259 00260 if(strcmp(str, "Shadow")==0) 00261 return SCE_PASS_SHADOW; 00262 00263 if(strcmp(str, "AO")==0) 00264 return SCE_PASS_AO; 00265 00266 if(strcmp(str, "Env")==0) 00267 return SCE_PASS_ENVIRONMENT; 00268 00269 if(strcmp(str, "Indirect")==0) 00270 return SCE_PASS_INDIRECT; 00271 00272 if(strcmp(str, "Reflect")==0) 00273 return SCE_PASS_REFLECT; 00274 00275 if(strcmp(str, "Refract")==0) 00276 return SCE_PASS_REFRACT; 00277 00278 if(strcmp(str, "IndexOB")==0) 00279 return SCE_PASS_INDEXOB; 00280 00281 if(strcmp(str, "IndexMA")==0) 00282 return SCE_PASS_INDEXMA; 00283 00284 if(strcmp(str, "Mist")==0) 00285 return SCE_PASS_MIST; 00286 00287 if(strcmp(str, "RayHits")==0) 00288 return SCE_PASS_RAYHITS; 00289 return 0; 00290 } 00291 00292 /********************************** New **************************************/ 00293 00294 static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype) 00295 { 00296 const char *typestr= get_pass_name(passtype, 0); 00297 RenderPass *rpass= MEM_callocN(sizeof(RenderPass), typestr); 00298 int rectsize= rr->rectx*rr->recty*channels; 00299 00300 BLI_addtail(&rl->passes, rpass); 00301 rpass->passtype= passtype; 00302 rpass->channels= channels; 00303 rpass->rectx= rl->rectx; 00304 rpass->recty= rl->recty; 00305 BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name)); 00306 00307 if(rr->exrhandle) { 00308 int a; 00309 for(a=0; a<channels; a++) 00310 IMB_exr_add_channel(rr->exrhandle, rl->name, get_pass_name(passtype, a), 0, 0, NULL); 00311 } 00312 else { 00313 float *rect; 00314 int x; 00315 00316 rpass->rect= MEM_mapallocN(sizeof(float)*rectsize, typestr); 00317 00318 if(passtype==SCE_PASS_VECTOR) { 00319 /* initialize to max speed */ 00320 rect= rpass->rect; 00321 for(x= rectsize-1; x>=0; x--) 00322 rect[x]= PASS_VECTOR_MAX; 00323 } 00324 else if(passtype==SCE_PASS_Z) { 00325 rect= rpass->rect; 00326 for(x= rectsize-1; x>=0; x--) 00327 rect[x]= 10e10; 00328 } 00329 } 00330 } 00331 00332 /* called by main render as well for parts */ 00333 /* will read info from Render *re to define layers */ 00334 /* called in threads */ 00335 /* re->winx,winy is coordinate space of entire image, partrct the part within */ 00336 RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuffers) 00337 { 00338 RenderResult *rr; 00339 RenderLayer *rl; 00340 SceneRenderLayer *srl; 00341 int rectx, recty, nr; 00342 00343 rectx= partrct->xmax - partrct->xmin; 00344 recty= partrct->ymax - partrct->ymin; 00345 00346 if(rectx<=0 || recty<=0) 00347 return NULL; 00348 00349 rr= MEM_callocN(sizeof(RenderResult), "new render result"); 00350 rr->rectx= rectx; 00351 rr->recty= recty; 00352 rr->renrect.xmin= 0; rr->renrect.xmax= rectx-2*crop; 00353 /* crop is one or two extra pixels rendered for filtering, is used for merging and display too */ 00354 rr->crop= crop; 00355 00356 /* tilerect is relative coordinates within render disprect. do not subtract crop yet */ 00357 rr->tilerect.xmin= partrct->xmin - re->disprect.xmin; 00358 rr->tilerect.xmax= partrct->xmax - re->disprect.xmax; 00359 rr->tilerect.ymin= partrct->ymin - re->disprect.ymin; 00360 rr->tilerect.ymax= partrct->ymax - re->disprect.ymax; 00361 00362 if(savebuffers) { 00363 rr->exrhandle= IMB_exr_get_handle(); 00364 } 00365 00366 /* check renderdata for amount of layers */ 00367 for(nr=0, srl= re->r.layers.first; srl; srl= srl->next, nr++) { 00368 00369 if((re->r.scemode & R_SINGLE_LAYER) && nr!=re->r.actlay) 00370 continue; 00371 if(srl->layflag & SCE_LAY_DISABLE) 00372 continue; 00373 00374 rl= MEM_callocN(sizeof(RenderLayer), "new render layer"); 00375 BLI_addtail(&rr->layers, rl); 00376 00377 BLI_strncpy(rl->name, srl->name, sizeof(rl->name)); 00378 rl->lay= srl->lay; 00379 rl->lay_zmask= srl->lay_zmask; 00380 rl->layflag= srl->layflag; 00381 rl->passflag= srl->passflag; // for debugging: srl->passflag|SCE_PASS_RAYHITS; 00382 rl->pass_xor= srl->pass_xor; 00383 rl->light_override= srl->light_override; 00384 rl->mat_override= srl->mat_override; 00385 rl->rectx= rectx; 00386 rl->recty= recty; 00387 00388 if(rr->exrhandle) { 00389 IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R", 0, 0, NULL); 00390 IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G", 0, 0, NULL); 00391 IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B", 0, 0, NULL); 00392 IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A", 0, 0, NULL); 00393 } 00394 else 00395 rl->rectf= MEM_mapallocN(rectx*recty*sizeof(float)*4, "Combined rgba"); 00396 00397 if(srl->passflag & SCE_PASS_Z) 00398 render_layer_add_pass(rr, rl, 1, SCE_PASS_Z); 00399 if(srl->passflag & SCE_PASS_VECTOR) 00400 render_layer_add_pass(rr, rl, 4, SCE_PASS_VECTOR); 00401 if(srl->passflag & SCE_PASS_NORMAL) 00402 render_layer_add_pass(rr, rl, 3, SCE_PASS_NORMAL); 00403 if(srl->passflag & SCE_PASS_UV) 00404 render_layer_add_pass(rr, rl, 3, SCE_PASS_UV); 00405 if(srl->passflag & SCE_PASS_RGBA) 00406 render_layer_add_pass(rr, rl, 4, SCE_PASS_RGBA); 00407 if(srl->passflag & SCE_PASS_EMIT) 00408 render_layer_add_pass(rr, rl, 3, SCE_PASS_EMIT); 00409 if(srl->passflag & SCE_PASS_DIFFUSE) 00410 render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE); 00411 if(srl->passflag & SCE_PASS_SPEC) 00412 render_layer_add_pass(rr, rl, 3, SCE_PASS_SPEC); 00413 if(srl->passflag & SCE_PASS_AO) 00414 render_layer_add_pass(rr, rl, 3, SCE_PASS_AO); 00415 if(srl->passflag & SCE_PASS_ENVIRONMENT) 00416 render_layer_add_pass(rr, rl, 3, SCE_PASS_ENVIRONMENT); 00417 if(srl->passflag & SCE_PASS_INDIRECT) 00418 render_layer_add_pass(rr, rl, 3, SCE_PASS_INDIRECT); 00419 if(srl->passflag & SCE_PASS_SHADOW) 00420 render_layer_add_pass(rr, rl, 3, SCE_PASS_SHADOW); 00421 if(srl->passflag & SCE_PASS_REFLECT) 00422 render_layer_add_pass(rr, rl, 3, SCE_PASS_REFLECT); 00423 if(srl->passflag & SCE_PASS_REFRACT) 00424 render_layer_add_pass(rr, rl, 3, SCE_PASS_REFRACT); 00425 if(srl->passflag & SCE_PASS_INDEXOB) 00426 render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB); 00427 if(srl->passflag & SCE_PASS_INDEXMA) 00428 render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXMA); 00429 if(srl->passflag & SCE_PASS_MIST) 00430 render_layer_add_pass(rr, rl, 1, SCE_PASS_MIST); 00431 if(rl->passflag & SCE_PASS_RAYHITS) 00432 render_layer_add_pass(rr, rl, 4, SCE_PASS_RAYHITS); 00433 00434 } 00435 /* sss, previewrender and envmap don't do layers, so we make a default one */ 00436 if(rr->layers.first==NULL) { 00437 rl= MEM_callocN(sizeof(RenderLayer), "new render layer"); 00438 BLI_addtail(&rr->layers, rl); 00439 00440 rl->rectx= rectx; 00441 rl->recty= recty; 00442 00443 /* duplicate code... */ 00444 if(rr->exrhandle) { 00445 IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R", 0, 0, NULL); 00446 IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G", 0, 0, NULL); 00447 IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B", 0, 0, NULL); 00448 IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A", 0, 0, NULL); 00449 } 00450 else 00451 rl->rectf= MEM_mapallocN(rectx*recty*sizeof(float)*4, "Combined rgba"); 00452 00453 /* note, this has to be in sync with scene.c */ 00454 rl->lay= (1<<20) -1; 00455 rl->layflag= 0x7FFF; /* solid ztra halo strand */ 00456 rl->passflag= SCE_PASS_COMBINED; 00457 00458 re->r.actlay= 0; 00459 } 00460 00461 /* border render; calculate offset for use in compositor. compo is centralized coords */ 00462 rr->xof= re->disprect.xmin + (re->disprect.xmax - re->disprect.xmin)/2 - re->winx/2; 00463 rr->yof= re->disprect.ymin + (re->disprect.ymax - re->disprect.ymin)/2 - re->winy/2; 00464 00465 return rr; 00466 } 00467 00468 /* allocate osa new results for samples */ 00469 RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *partrct, int crop, int savebuffers) 00470 { 00471 int a; 00472 00473 if(re->osa==0) 00474 return render_result_new(re, partrct, crop, savebuffers); 00475 00476 for(a=0; a<re->osa; a++) { 00477 RenderResult *rr= render_result_new(re, partrct, crop, savebuffers); 00478 BLI_addtail(lb, rr); 00479 rr->sample_nr= a; 00480 } 00481 00482 return lb->first; 00483 } 00484 00485 /* callbacks for render_result_new_from_exr */ 00486 static void *ml_addlayer_cb(void *base, char *str) 00487 { 00488 RenderResult *rr= base; 00489 RenderLayer *rl; 00490 00491 rl= MEM_callocN(sizeof(RenderLayer), "new render layer"); 00492 BLI_addtail(&rr->layers, rl); 00493 00494 BLI_strncpy(rl->name, str, EXR_LAY_MAXNAME); 00495 return rl; 00496 } 00497 00498 static void ml_addpass_cb(void *UNUSED(base), void *lay, char *str, float *rect, int totchan, char *chan_id) 00499 { 00500 RenderLayer *rl= lay; 00501 RenderPass *rpass= MEM_callocN(sizeof(RenderPass), "loaded pass"); 00502 int a; 00503 00504 BLI_addtail(&rl->passes, rpass); 00505 rpass->channels= totchan; 00506 00507 rpass->passtype= passtype_from_name(str); 00508 if(rpass->passtype==0) printf("unknown pass %s\n", str); 00509 rl->passflag |= rpass->passtype; 00510 00511 BLI_strncpy(rpass->name, str, EXR_PASS_MAXNAME); 00512 /* channel id chars */ 00513 for(a=0; a<totchan; a++) 00514 rpass->chan_id[a]= chan_id[a]; 00515 00516 rpass->rect= rect; 00517 } 00518 00519 /* from imbuf, if a handle was returned we convert this to render result */ 00520 RenderResult *render_result_new_from_exr(void *exrhandle, int rectx, int recty) 00521 { 00522 RenderResult *rr= MEM_callocN(sizeof(RenderResult), "loaded render result"); 00523 RenderLayer *rl; 00524 RenderPass *rpass; 00525 00526 rr->rectx= rectx; 00527 rr->recty= recty; 00528 00529 IMB_exr_multilayer_convert(exrhandle, rr, ml_addlayer_cb, ml_addpass_cb); 00530 00531 for(rl=rr->layers.first; rl; rl=rl->next) { 00532 rl->rectx= rectx; 00533 rl->recty= recty; 00534 00535 for(rpass=rl->passes.first; rpass; rpass=rpass->next) { 00536 rpass->rectx= rectx; 00537 rpass->recty= recty; 00538 } 00539 } 00540 00541 return rr; 00542 } 00543 00544 /*********************************** Merge ***********************************/ 00545 00546 static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize) 00547 { 00548 int y, ofs, copylen, tilex, tiley; 00549 00550 copylen= tilex= rrpart->rectx; 00551 tiley= rrpart->recty; 00552 00553 if(rrpart->crop) { /* filters add pixel extra */ 00554 tile+= pixsize*(rrpart->crop + rrpart->crop*tilex); 00555 00556 copylen= tilex - 2*rrpart->crop; 00557 tiley -= 2*rrpart->crop; 00558 00559 ofs= (rrpart->tilerect.ymin + rrpart->crop)*rr->rectx + (rrpart->tilerect.xmin+rrpart->crop); 00560 target+= pixsize*ofs; 00561 } 00562 else { 00563 ofs= (rrpart->tilerect.ymin*rr->rectx + rrpart->tilerect.xmin); 00564 target+= pixsize*ofs; 00565 } 00566 00567 copylen *= sizeof(float)*pixsize; 00568 tilex *= pixsize; 00569 ofs= pixsize*rr->rectx; 00570 00571 for(y=0; y<tiley; y++) { 00572 memcpy(target, tile, copylen); 00573 target+= ofs; 00574 tile+= tilex; 00575 } 00576 } 00577 00578 /* used when rendering to a full buffer, or when reading the exr part-layer-pass file */ 00579 /* no test happens here if it fits... we also assume layers are in sync */ 00580 /* is used within threads */ 00581 void render_result_merge(RenderResult *rr, RenderResult *rrpart) 00582 { 00583 RenderLayer *rl, *rlp; 00584 RenderPass *rpass, *rpassp; 00585 00586 for(rl= rr->layers.first, rlp= rrpart->layers.first; rl && rlp; rl= rl->next, rlp= rlp->next) { 00587 00588 /* combined */ 00589 if(rl->rectf && rlp->rectf) 00590 do_merge_tile(rr, rrpart, rl->rectf, rlp->rectf, 4); 00591 00592 /* passes are allocated in sync */ 00593 for(rpass= rl->passes.first, rpassp= rlp->passes.first; rpass && rpassp; rpass= rpass->next, rpassp= rpassp->next) { 00594 do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels); 00595 } 00596 } 00597 } 00598 00599 /* for passes read from files, these have names stored */ 00600 static char *make_pass_name(RenderPass *rpass, int chan) 00601 { 00602 static char name[16]; 00603 int len; 00604 00605 BLI_strncpy(name, rpass->name, EXR_PASS_MAXNAME); 00606 len= strlen(name); 00607 name[len]= '.'; 00608 name[len+1]= rpass->chan_id[chan]; 00609 name[len+2]= 0; 00610 00611 return name; 00612 } 00613 00614 /* filename already made absolute */ 00615 /* called from within UI, saves both rendered result as a file-read result */ 00616 int RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, int compress) 00617 { 00618 RenderLayer *rl; 00619 RenderPass *rpass; 00620 void *exrhandle= IMB_exr_get_handle(); 00621 int success; 00622 00623 BLI_make_existing_file(filename); 00624 00625 /* composite result */ 00626 if(rr->rectf) { 00627 IMB_exr_add_channel(exrhandle, "Composite", "Combined.R", 4, 4*rr->rectx, rr->rectf); 00628 IMB_exr_add_channel(exrhandle, "Composite", "Combined.G", 4, 4*rr->rectx, rr->rectf+1); 00629 IMB_exr_add_channel(exrhandle, "Composite", "Combined.B", 4, 4*rr->rectx, rr->rectf+2); 00630 IMB_exr_add_channel(exrhandle, "Composite", "Combined.A", 4, 4*rr->rectx, rr->rectf+3); 00631 } 00632 00633 /* add layers/passes and assign channels */ 00634 for(rl= rr->layers.first; rl; rl= rl->next) { 00635 00636 /* combined */ 00637 if(rl->rectf) { 00638 int a, xstride= 4; 00639 for(a=0; a<xstride; a++) 00640 IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), 00641 xstride, xstride*rr->rectx, rl->rectf+a); 00642 } 00643 00644 /* passes are allocated in sync */ 00645 for(rpass= rl->passes.first; rpass; rpass= rpass->next) { 00646 int a, xstride= rpass->channels; 00647 for(a=0; a<xstride; a++) { 00648 if(rpass->passtype) 00649 IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), 00650 xstride, xstride*rr->rectx, rpass->rect+a); 00651 else 00652 IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), 00653 xstride, xstride*rr->rectx, rpass->rect+a); 00654 } 00655 } 00656 } 00657 00658 /* when the filename has no permissions, this can fail */ 00659 if(IMB_exr_begin_write(exrhandle, filename, rr->rectx, rr->recty, compress)) { 00660 IMB_exr_write_channels(exrhandle); 00661 success= TRUE; 00662 } 00663 else { 00664 /* TODO, get the error from openexr's exception */ 00665 BKE_report(reports, RPT_ERROR, "Error Writing Render Result, see console"); 00666 success= FALSE; 00667 } 00668 IMB_exr_close(exrhandle); 00669 00670 return success; 00671 } 00672 00673 /**************************** Single Layer Rendering *************************/ 00674 00675 void render_result_single_layer_begin(Render *re) 00676 { 00677 /* all layers except the active one get temporally pushed away */ 00678 00679 /* officially pushed result should be NULL... error can happen with do_seq */ 00680 RE_FreeRenderResult(re->pushedresult); 00681 00682 re->pushedresult= re->result; 00683 re->result= NULL; 00684 } 00685 00686 /* if scemode is R_SINGLE_LAYER, at end of rendering, merge the both render results */ 00687 void render_result_single_layer_end(Render *re) 00688 { 00689 SceneRenderLayer *srl; 00690 RenderLayer *rlpush; 00691 RenderLayer *rl; 00692 int nr; 00693 00694 if(re->result==NULL) { 00695 printf("pop render result error; no current result!\n"); 00696 return; 00697 } 00698 00699 if(!re->pushedresult) 00700 return; 00701 00702 if(re->pushedresult->rectx==re->result->rectx && re->pushedresult->recty==re->result->recty) { 00703 /* find which layer in re->pushedresult should be replaced */ 00704 rl= re->result->layers.first; 00705 00706 /* render result should be empty after this */ 00707 BLI_remlink(&re->result->layers, rl); 00708 00709 /* reconstruct render result layers */ 00710 for(nr=0, srl= re->scene->r.layers.first; srl; srl= srl->next, nr++) { 00711 if(nr==re->r.actlay) 00712 BLI_addtail(&re->result->layers, rl); 00713 else { 00714 rlpush= RE_GetRenderLayer(re->pushedresult, srl->name); 00715 if(rlpush) { 00716 BLI_remlink(&re->pushedresult->layers, rlpush); 00717 BLI_addtail(&re->result->layers, rlpush); 00718 } 00719 } 00720 } 00721 } 00722 00723 RE_FreeRenderResult(re->pushedresult); 00724 re->pushedresult= NULL; 00725 } 00726 00727 /************************* EXR Tile File Rendering ***************************/ 00728 00729 static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart) 00730 { 00731 RenderLayer *rlp; 00732 RenderPass *rpassp; 00733 int offs, partx, party; 00734 00735 BLI_lock_thread(LOCK_IMAGE); 00736 00737 for(rlp= rrpart->layers.first; rlp; rlp= rlp->next) { 00738 00739 if(rrpart->crop) { /* filters add pixel extra */ 00740 offs= (rrpart->crop + rrpart->crop*rrpart->rectx); 00741 } 00742 else { 00743 offs= 0; 00744 } 00745 00746 /* combined */ 00747 if(rlp->rectf) { 00748 int a, xstride= 4; 00749 for(a=0; a<xstride; a++) 00750 IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(SCE_PASS_COMBINED, a), 00751 xstride, xstride*rrpart->rectx, rlp->rectf+a + xstride*offs); 00752 } 00753 00754 /* passes are allocated in sync */ 00755 for(rpassp= rlp->passes.first; rpassp; rpassp= rpassp->next) { 00756 int a, xstride= rpassp->channels; 00757 for(a=0; a<xstride; a++) 00758 IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a), 00759 xstride, xstride*rrpart->rectx, rpassp->rect+a + xstride*offs); 00760 } 00761 00762 } 00763 00764 party= rrpart->tilerect.ymin + rrpart->crop; 00765 partx= rrpart->tilerect.xmin + rrpart->crop; 00766 IMB_exrtile_write_channels(rr->exrhandle, partx, party, 0); 00767 00768 BLI_unlock_thread(LOCK_IMAGE); 00769 } 00770 00771 static void save_empty_result_tiles(Render *re) 00772 { 00773 RenderPart *pa; 00774 RenderResult *rr; 00775 00776 for(rr= re->result; rr; rr= rr->next) { 00777 IMB_exrtile_clear_channels(rr->exrhandle); 00778 00779 for(pa= re->parts.first; pa; pa= pa->next) { 00780 if(pa->ready==0) { 00781 int party= pa->disprect.ymin - re->disprect.ymin + pa->crop; 00782 int partx= pa->disprect.xmin - re->disprect.xmin + pa->crop; 00783 IMB_exrtile_write_channels(rr->exrhandle, partx, party, 0); 00784 } 00785 } 00786 } 00787 } 00788 00789 /* begin write of exr tile file */ 00790 void render_result_exr_file_begin(Render *re) 00791 { 00792 RenderResult *rr; 00793 char str[FILE_MAX]; 00794 00795 for(rr= re->result; rr; rr= rr->next) { 00796 render_result_exr_file_path(re->scene, rr->sample_nr, str); 00797 00798 printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str); 00799 IMB_exrtile_begin_write(rr->exrhandle, str, 0, rr->rectx, rr->recty, re->partx, re->party); 00800 } 00801 } 00802 00803 /* end write of exr tile file, read back first sample */ 00804 void render_result_exr_file_end(Render *re) 00805 { 00806 RenderResult *rr; 00807 00808 save_empty_result_tiles(re); 00809 00810 for(rr= re->result; rr; rr= rr->next) { 00811 IMB_exr_close(rr->exrhandle); 00812 rr->exrhandle= NULL; 00813 } 00814 00815 render_result_free_list(&re->fullresult, re->result); 00816 re->result= NULL; 00817 00818 render_result_exr_file_read(re, 0); 00819 } 00820 00821 /* save part into exr file */ 00822 void render_result_exr_file_merge(RenderResult *rr, RenderResult *rrpart) 00823 { 00824 for(; rr && rrpart; rr= rr->next, rrpart= rrpart->next) 00825 save_render_result_tile(rr, rrpart); 00826 } 00827 00828 /* path to temporary exr file */ 00829 void render_result_exr_file_path(Scene *scene, int sample, char *filepath) 00830 { 00831 char di[FILE_MAX], name[FILE_MAXFILE+MAX_ID_NAME+100], fi[FILE_MAXFILE]; 00832 00833 BLI_strncpy(di, G.main->name, FILE_MAX); 00834 BLI_splitdirstring(di, fi); 00835 00836 if(sample==0) 00837 BLI_snprintf(name, sizeof(name), "%s_%s.exr", fi, scene->id.name+2); 00838 else 00839 BLI_snprintf(name, sizeof(name), "%s_%s%d.exr", fi, scene->id.name+2, sample); 00840 00841 BLI_make_file_string("/", filepath, BLI_temporary_dir(), name); 00842 } 00843 00844 /* only for temp buffer files, makes exact copy of render result */ 00845 int render_result_exr_file_read(Render *re, int sample) 00846 { 00847 char str[FILE_MAX]; 00848 int success; 00849 00850 RE_FreeRenderResult(re->result); 00851 re->result= render_result_new(re, &re->disprect, 0, RR_USE_MEM); 00852 00853 render_result_exr_file_path(re->scene, sample, str); 00854 printf("read exr tmp file: %s\n", str); 00855 00856 if(render_result_exr_file_read_path(re->result, str)) { 00857 success= TRUE; 00858 } 00859 else { 00860 printf("cannot read: %s\n", str); 00861 success= FALSE; 00862 00863 } 00864 00865 return success; 00866 } 00867 00868 /* called for reading temp files, and for external engines */ 00869 int render_result_exr_file_read_path(RenderResult *rr, const char *filepath) 00870 { 00871 RenderLayer *rl; 00872 RenderPass *rpass; 00873 void *exrhandle= IMB_exr_get_handle(); 00874 int rectx, recty; 00875 00876 if(IMB_exr_begin_read(exrhandle, filepath, &rectx, &recty)==0) { 00877 printf("failed being read %s\n", filepath); 00878 IMB_exr_close(exrhandle); 00879 return 0; 00880 } 00881 00882 if(rr == NULL || rectx!=rr->rectx || recty!=rr->recty) { 00883 if(rr) 00884 printf("error in reading render result: dimensions don't match\n"); 00885 else 00886 printf("error in reading render result: NULL result pointer\n"); 00887 IMB_exr_close(exrhandle); 00888 return 0; 00889 } 00890 00891 for(rl= rr->layers.first; rl; rl= rl->next) { 00892 /* combined */ 00893 if(rl->rectf) { 00894 int a, xstride= 4; 00895 for(a=0; a<xstride; a++) 00896 IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), 00897 xstride, xstride*rectx, rl->rectf+a); 00898 } 00899 00900 /* passes are allocated in sync */ 00901 for(rpass= rl->passes.first; rpass; rpass= rpass->next) { 00902 int a, xstride= rpass->channels; 00903 for(a=0; a<xstride; a++) 00904 IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), 00905 xstride, xstride*rectx, rpass->rect+a); 00906 00907 BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name)); 00908 } 00909 } 00910 00911 IMB_exr_read_channels(exrhandle); 00912 IMB_exr_close(exrhandle); 00913 00914 return 1; 00915 } 00916 00917 /*************************** Combined Pixel Rect *****************************/ 00918 00919 ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd) 00920 { 00921 int flags = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE)? IB_cm_predivide: 0; 00922 ImBuf *ibuf= IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, flags); 00923 00924 /* if not exists, BKE_write_ibuf makes one */ 00925 ibuf->rect= (unsigned int *)rr->rect32; 00926 ibuf->rect_float= rr->rectf; 00927 ibuf->zbuf_float= rr->rectz; 00928 00929 /* float factor for random dither, imbuf takes care of it */ 00930 ibuf->dither= rd->dither_intensity; 00931 00932 /* prepare to gamma correct to sRGB color space */ 00933 if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) { 00934 /* sequence editor can generate 8bpc render buffers */ 00935 if (ibuf->rect) { 00936 ibuf->profile = IB_PROFILE_SRGB; 00937 if (BKE_imtype_valid_depths(rd->im_format.imtype) & (R_IMF_CHAN_DEPTH_12|R_IMF_CHAN_DEPTH_16|R_IMF_CHAN_DEPTH_24|R_IMF_CHAN_DEPTH_32)) 00938 IMB_float_from_rect(ibuf); 00939 } else { 00940 ibuf->profile = IB_PROFILE_LINEAR_RGB; 00941 } 00942 } 00943 00944 /* color -> greyscale */ 00945 /* editing directly would alter the render view */ 00946 if(rd->im_format.planes == R_IMF_PLANES_BW) { 00947 ImBuf *ibuf_bw= IMB_dupImBuf(ibuf); 00948 IMB_color_to_bw(ibuf_bw); 00949 IMB_freeImBuf(ibuf); 00950 ibuf= ibuf_bw; 00951 } 00952 00953 return ibuf; 00954 } 00955 00956 void render_result_rect_from_ibuf(RenderResult *rr, RenderData *rd, ImBuf *ibuf) 00957 { 00958 if(ibuf->rect_float) { 00959 /* color management: when off ensure rectf is non-lin, since thats what the internal 00960 * render engine delivers */ 00961 int profile_to= (rd->color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB; 00962 int profile_from= (ibuf->profile == IB_PROFILE_LINEAR_RGB)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB; 00963 int predivide= (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE); 00964 00965 if (!rr->rectf) 00966 rr->rectf= MEM_mallocN(4*sizeof(float)*rr->rectx*rr->recty, "render_seq rectf"); 00967 00968 IMB_buffer_float_from_float(rr->rectf, ibuf->rect_float, 00969 4, profile_to, profile_from, predivide, 00970 rr->rectx, rr->recty, rr->rectx, rr->rectx); 00971 00972 /* TSK! Since sequence render doesn't free the *rr render result, the old rect32 00973 can hang around when sequence render has rendered a 32 bits one before */ 00974 if(rr->rect32) { 00975 MEM_freeN(rr->rect32); 00976 rr->rect32= NULL; 00977 } 00978 } 00979 else if(ibuf->rect) { 00980 if (!rr->rect32) 00981 rr->rect32= MEM_mallocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect"); 00982 00983 memcpy(rr->rect32, ibuf->rect, 4*rr->rectx*rr->recty); 00984 00985 /* Same things as above, old rectf can hang around from previous render. */ 00986 if(rr->rectf) { 00987 MEM_freeN(rr->rectf); 00988 rr->rectf= NULL; 00989 } 00990 } 00991 } 00992 00993 void render_result_rect_fill_zero(RenderResult *rr) 00994 { 00995 if (rr->rectf) 00996 memset(rr->rectf, 0, 4*sizeof(float)*rr->rectx*rr->recty); 00997 else if (rr->rect32) 00998 memset(rr->rect32, 0, 4*rr->rectx*rr->recty); 00999 else 01000 rr->rect32= MEM_callocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect"); 01001 } 01002 01003 void render_result_rect_get_pixels(RenderResult *rr, RenderData *rd, unsigned int *rect, int rectx, int recty) 01004 { 01005 if(rr->rect32) { 01006 memcpy(rect, rr->rect32, sizeof(int)*rr->rectx*rr->recty); 01007 } 01008 else if(rr->rectf) { 01009 int profile_from= (rd->color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB; 01010 int predivide= (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE); 01011 int dither= 0; 01012 01013 IMB_buffer_byte_from_float((unsigned char*)rect, rr->rectf, 01014 4, dither, IB_PROFILE_SRGB, profile_from, predivide, 01015 rr->rectx, rr->recty, rr->rectx, rr->rectx); 01016 } 01017 else 01018 /* else fill with black */ 01019 memset(rect, 0, sizeof(int)*rectx*recty); 01020 } 01021