|
Blender
V2.59
|
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 00034 #include <math.h> 00035 #include <limits.h> 00036 #include <string.h> 00037 #include <stdlib.h> 00038 #include <stddef.h> 00039 00040 #include "DNA_group_types.h" 00041 #include "DNA_image_types.h" 00042 #include "DNA_node_types.h" 00043 #include "DNA_object_types.h" 00044 #include "DNA_scene_types.h" 00045 #include "DNA_sequence_types.h" 00046 #include "DNA_userdef_types.h" 00047 00048 #include "MEM_guardedalloc.h" 00049 00050 #include "BKE_animsys.h" /* <------ should this be here?, needed for sequencer update */ 00051 #include "BKE_global.h" 00052 #include "BKE_image.h" 00053 #include "BKE_main.h" 00054 #include "BKE_node.h" 00055 #include "BKE_object.h" 00056 #include "BKE_pointcache.h" 00057 #include "BKE_report.h" 00058 #include "BKE_scene.h" 00059 #include "BKE_sequencer.h" 00060 #include "BKE_utildefines.h" 00061 #include "BKE_writeavi.h" /* <------ should be replaced once with generic movie module */ 00062 00063 #include "BLI_math.h" 00064 #include "BLI_blenlib.h" 00065 #include "BLI_rand.h" 00066 #include "BLI_threads.h" 00067 #include "BLI_callbacks.h" 00068 #include "BLI_utildefines.h" 00069 00070 #include "PIL_time.h" 00071 #include "IMB_imbuf.h" 00072 #include "IMB_imbuf_types.h" 00073 00074 #include "intern/openexr/openexr_multi.h" 00075 00076 #include "RE_pipeline.h" 00077 00078 /* internal */ 00079 #include "render_types.h" 00080 #include "renderpipeline.h" 00081 #include "renderdatabase.h" 00082 #include "rendercore.h" 00083 #include "envmap.h" 00084 #include "initrender.h" 00085 #include "shadbuf.h" 00086 #include "pixelblending.h" 00087 #include "zbuf.h" 00088 00089 00090 /* render flow 00091 00092 1) Initialize state 00093 - state data, tables 00094 - movie/image file init 00095 - everything that doesn't change during animation 00096 00097 2) Initialize data 00098 - camera, world, matrices 00099 - make render verts, faces, halos, strands 00100 - everything can change per frame/field 00101 00102 3) Render Processor 00103 - multiple layers 00104 - tiles, rect, baking 00105 - layers/tiles optionally to disk or directly in Render Result 00106 00107 4) Composite Render Result 00108 - also read external files etc 00109 00110 5) Image Files 00111 - save file or append in movie 00112 00113 */ 00114 00115 00116 /* ********* globals ******** */ 00117 00118 /* here we store all renders */ 00119 static struct { 00120 ListBase renderlist; 00121 00122 /* commandline thread override */ 00123 int threads; 00124 } RenderGlobal = {{NULL, NULL}, -1}; 00125 00126 /* hardcopy of current render, used while rendering for speed */ 00127 Render R; 00128 00129 /* ********* alloc and free ******** */ 00130 00131 static int do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh, const char *name_override); 00132 00133 static volatile int g_break= 0; 00134 static int thread_break(void *UNUSED(arg)) 00135 { 00136 return g_break; 00137 } 00138 00139 /* default callbacks, set in each new render */ 00140 static void result_nothing(void *UNUSED(arg), RenderResult *UNUSED(rr)) {} 00141 static void result_rcti_nothing(void *UNUSED(arg), RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect)) {} 00142 static void stats_nothing(void *UNUSED(arg), RenderStats *UNUSED(rs)) {} 00143 static void float_nothing(void *UNUSED(arg), float UNUSED(val)) {} 00144 static int default_break(void *UNUSED(arg)) {return G.afbreek == 1;} 00145 00146 static void stats_background(void *UNUSED(arg), RenderStats *rs) 00147 { 00148 uintptr_t mem_in_use, mmap_in_use, peak_memory; 00149 float megs_used_memory, mmap_used_memory, megs_peak_memory; 00150 00151 mem_in_use= MEM_get_memory_in_use(); 00152 mmap_in_use= MEM_get_mapped_memory_in_use(); 00153 peak_memory = MEM_get_peak_memory(); 00154 00155 megs_used_memory= (mem_in_use-mmap_in_use)/(1024.0*1024.0); 00156 mmap_used_memory= (mmap_in_use)/(1024.0*1024.0); 00157 megs_peak_memory = (peak_memory)/(1024.0*1024.0); 00158 00159 fprintf(stdout, "Fra:%d Mem:%.2fM (%.2fM, peak %.2fM) ", rs->cfra, 00160 megs_used_memory, mmap_used_memory, megs_peak_memory); 00161 00162 if(rs->curfield) 00163 fprintf(stdout, "Field %d ", rs->curfield); 00164 if(rs->curblur) 00165 fprintf(stdout, "Blur %d ", rs->curblur); 00166 00167 if(rs->infostr) { 00168 fprintf(stdout, "| %s", rs->infostr); 00169 } 00170 else { 00171 if(rs->tothalo) 00172 fprintf(stdout, "Sce: %s Ve:%d Fa:%d Ha:%d La:%d", rs->scenename, rs->totvert, rs->totface, rs->tothalo, rs->totlamp); 00173 else 00174 fprintf(stdout, "Sce: %s Ve:%d Fa:%d La:%d", rs->scenename, rs->totvert, rs->totface, rs->totlamp); 00175 } 00176 fputc('\n', stdout); 00177 fflush(stdout); 00178 } 00179 00180 void RE_FreeRenderResult(RenderResult *res) 00181 { 00182 if(res==NULL) return; 00183 00184 while(res->layers.first) { 00185 RenderLayer *rl= res->layers.first; 00186 00187 if(rl->rectf) MEM_freeN(rl->rectf); 00188 /* acolrect and scolrect are optionally allocated in shade_tile, only free here since it can be used for drawing */ 00189 if(rl->acolrect) MEM_freeN(rl->acolrect); 00190 if(rl->scolrect) MEM_freeN(rl->scolrect); 00191 00192 while(rl->passes.first) { 00193 RenderPass *rpass= rl->passes.first; 00194 if(rpass->rect) MEM_freeN(rpass->rect); 00195 BLI_remlink(&rl->passes, rpass); 00196 MEM_freeN(rpass); 00197 } 00198 BLI_remlink(&res->layers, rl); 00199 MEM_freeN(rl); 00200 } 00201 00202 if(res->rect32) 00203 MEM_freeN(res->rect32); 00204 if(res->rectz) 00205 MEM_freeN(res->rectz); 00206 if(res->rectf) 00207 MEM_freeN(res->rectf); 00208 if(res->text) 00209 MEM_freeN(res->text); 00210 00211 MEM_freeN(res); 00212 } 00213 00214 /* version that's compatible with fullsample buffers */ 00215 static void free_render_result(ListBase *lb, RenderResult *rr) 00216 { 00217 RenderResult *rrnext; 00218 00219 for(; rr; rr= rrnext) { 00220 rrnext= rr->next; 00221 00222 if(lb && lb->first) 00223 BLI_remlink(lb, rr); 00224 00225 RE_FreeRenderResult(rr); 00226 } 00227 } 00228 00229 00230 /* all layers except the active one get temporally pushed away */ 00231 static void push_render_result(Render *re) 00232 { 00233 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 00234 00235 /* officially pushed result should be NULL... error can happen with do_seq */ 00236 RE_FreeRenderResult(re->pushedresult); 00237 00238 re->pushedresult= re->result; 00239 re->result= NULL; 00240 00241 BLI_rw_mutex_unlock(&re->resultmutex); 00242 } 00243 00244 /* if scemode is R_SINGLE_LAYER, at end of rendering, merge the both render results */ 00245 static void pop_render_result(Render *re) 00246 { 00247 if(re->result==NULL) { 00248 printf("pop render result error; no current result!\n"); 00249 return; 00250 } 00251 00252 if(re->pushedresult) { 00253 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 00254 00255 if(re->pushedresult->rectx==re->result->rectx && re->pushedresult->recty==re->result->recty) { 00256 /* find which layer in pushedresult should be replaced */ 00257 SceneRenderLayer *srl; 00258 RenderLayer *rlpush; 00259 RenderLayer *rl= re->result->layers.first; 00260 int nr; 00261 00262 /* render result should be empty after this */ 00263 BLI_remlink(&re->result->layers, rl); 00264 00265 /* reconstruct render result layers */ 00266 for(nr=0, srl= re->scene->r.layers.first; srl; srl= srl->next, nr++) { 00267 if(nr==re->r.actlay) 00268 BLI_addtail(&re->result->layers, rl); 00269 else { 00270 rlpush= RE_GetRenderLayer(re->pushedresult, srl->name); 00271 if(rlpush) { 00272 BLI_remlink(&re->pushedresult->layers, rlpush); 00273 BLI_addtail(&re->result->layers, rlpush); 00274 } 00275 } 00276 } 00277 } 00278 00279 RE_FreeRenderResult(re->pushedresult); 00280 re->pushedresult= NULL; 00281 00282 BLI_rw_mutex_unlock(&re->resultmutex); 00283 } 00284 } 00285 00286 /* NOTE: OpenEXR only supports 32 chars for layer+pass names 00287 In blender we now use max 10 chars for pass, max 20 for layer */ 00288 static const char *get_pass_name(int passtype, int channel) 00289 { 00290 00291 if(passtype == SCE_PASS_COMBINED) { 00292 if(channel==-1) return "Combined"; 00293 if(channel==0) return "Combined.R"; 00294 if(channel==1) return "Combined.G"; 00295 if(channel==2) return "Combined.B"; 00296 return "Combined.A"; 00297 } 00298 if(passtype == SCE_PASS_Z) { 00299 if(channel==-1) return "Depth"; 00300 return "Depth.Z"; 00301 } 00302 if(passtype == SCE_PASS_VECTOR) { 00303 if(channel==-1) return "Vector"; 00304 if(channel==0) return "Vector.X"; 00305 if(channel==1) return "Vector.Y"; 00306 if(channel==2) return "Vector.Z"; 00307 return "Vector.W"; 00308 } 00309 if(passtype == SCE_PASS_NORMAL) { 00310 if(channel==-1) return "Normal"; 00311 if(channel==0) return "Normal.X"; 00312 if(channel==1) return "Normal.Y"; 00313 return "Normal.Z"; 00314 } 00315 if(passtype == SCE_PASS_UV) { 00316 if(channel==-1) return "UV"; 00317 if(channel==0) return "UV.U"; 00318 if(channel==1) return "UV.V"; 00319 return "UV.A"; 00320 } 00321 if(passtype == SCE_PASS_RGBA) { 00322 if(channel==-1) return "Color"; 00323 if(channel==0) return "Color.R"; 00324 if(channel==1) return "Color.G"; 00325 if(channel==2) return "Color.B"; 00326 return "Color.A"; 00327 } 00328 if(passtype == SCE_PASS_EMIT) { 00329 if(channel==-1) return "Emit"; 00330 if(channel==0) return "Emit.R"; 00331 if(channel==1) return "Emit.G"; 00332 return "Emit.B"; 00333 } 00334 if(passtype == SCE_PASS_DIFFUSE) { 00335 if(channel==-1) return "Diffuse"; 00336 if(channel==0) return "Diffuse.R"; 00337 if(channel==1) return "Diffuse.G"; 00338 return "Diffuse.B"; 00339 } 00340 if(passtype == SCE_PASS_SPEC) { 00341 if(channel==-1) return "Spec"; 00342 if(channel==0) return "Spec.R"; 00343 if(channel==1) return "Spec.G"; 00344 return "Spec.B"; 00345 } 00346 if(passtype == SCE_PASS_SHADOW) { 00347 if(channel==-1) return "Shadow"; 00348 if(channel==0) return "Shadow.R"; 00349 if(channel==1) return "Shadow.G"; 00350 return "Shadow.B"; 00351 } 00352 if(passtype == SCE_PASS_AO) { 00353 if(channel==-1) return "AO"; 00354 if(channel==0) return "AO.R"; 00355 if(channel==1) return "AO.G"; 00356 return "AO.B"; 00357 } 00358 if(passtype == SCE_PASS_ENVIRONMENT) { 00359 if(channel==-1) return "Env"; 00360 if(channel==0) return "Env.R"; 00361 if(channel==1) return "Env.G"; 00362 return "Env.B"; 00363 } 00364 if(passtype == SCE_PASS_INDIRECT) { 00365 if(channel==-1) return "Indirect"; 00366 if(channel==0) return "Indirect.R"; 00367 if(channel==1) return "Indirect.G"; 00368 return "Indirect.B"; 00369 } 00370 if(passtype == SCE_PASS_REFLECT) { 00371 if(channel==-1) return "Reflect"; 00372 if(channel==0) return "Reflect.R"; 00373 if(channel==1) return "Reflect.G"; 00374 return "Reflect.B"; 00375 } 00376 if(passtype == SCE_PASS_REFRACT) { 00377 if(channel==-1) return "Refract"; 00378 if(channel==0) return "Refract.R"; 00379 if(channel==1) return "Refract.G"; 00380 return "Refract.B"; 00381 } 00382 if(passtype == SCE_PASS_INDEXOB) { 00383 if(channel==-1) return "IndexOB"; 00384 return "IndexOB.X"; 00385 } 00386 if(passtype == SCE_PASS_INDEXMA) { 00387 if(channel==-1) return "IndexMA"; 00388 return "IndexMA.X"; 00389 } 00390 if(passtype == SCE_PASS_MIST) { 00391 if(channel==-1) return "Mist"; 00392 return "Mist.Z"; 00393 } 00394 if(passtype == SCE_PASS_RAYHITS) 00395 { 00396 if(channel==-1) return "Rayhits"; 00397 if(channel==0) return "Rayhits.R"; 00398 if(channel==1) return "Rayhits.G"; 00399 return "Rayhits.B"; 00400 } 00401 return "Unknown"; 00402 } 00403 00404 static int passtype_from_name(char *str) 00405 { 00406 00407 if(strcmp(str, "Combined")==0) 00408 return SCE_PASS_COMBINED; 00409 00410 if(strcmp(str, "Depth")==0) 00411 return SCE_PASS_Z; 00412 00413 if(strcmp(str, "Vector")==0) 00414 return SCE_PASS_VECTOR; 00415 00416 if(strcmp(str, "Normal")==0) 00417 return SCE_PASS_NORMAL; 00418 00419 if(strcmp(str, "UV")==0) 00420 return SCE_PASS_UV; 00421 00422 if(strcmp(str, "Color")==0) 00423 return SCE_PASS_RGBA; 00424 00425 if(strcmp(str, "Emit")==0) 00426 return SCE_PASS_EMIT; 00427 00428 if(strcmp(str, "Diffuse")==0) 00429 return SCE_PASS_DIFFUSE; 00430 00431 if(strcmp(str, "Spec")==0) 00432 return SCE_PASS_SPEC; 00433 00434 if(strcmp(str, "Shadow")==0) 00435 return SCE_PASS_SHADOW; 00436 00437 if(strcmp(str, "AO")==0) 00438 return SCE_PASS_AO; 00439 00440 if(strcmp(str, "Env")==0) 00441 return SCE_PASS_ENVIRONMENT; 00442 00443 if(strcmp(str, "Indirect")==0) 00444 return SCE_PASS_INDIRECT; 00445 00446 if(strcmp(str, "Reflect")==0) 00447 return SCE_PASS_REFLECT; 00448 00449 if(strcmp(str, "Refract")==0) 00450 return SCE_PASS_REFRACT; 00451 00452 if(strcmp(str, "IndexOB")==0) 00453 return SCE_PASS_INDEXOB; 00454 00455 if(strcmp(str, "IndexMA")==0) 00456 return SCE_PASS_INDEXMA; 00457 00458 if(strcmp(str, "Mist")==0) 00459 return SCE_PASS_MIST; 00460 00461 if(strcmp(str, "RayHits")==0) 00462 return SCE_PASS_RAYHITS; 00463 return 0; 00464 } 00465 00466 static void scene_unique_exr_name(Scene *scene, char *str, int sample) 00467 { 00468 char di[FILE_MAX], name[FILE_MAXFILE+MAX_ID_NAME+100], fi[FILE_MAXFILE]; 00469 00470 BLI_strncpy(di, G.main->name, FILE_MAX); 00471 BLI_splitdirstring(di, fi); 00472 00473 if(sample==0) 00474 BLI_snprintf(name, sizeof(name), "%s_%s.exr", fi, scene->id.name+2); 00475 else 00476 BLI_snprintf(name, sizeof(name), "%s_%s%d.exr", fi, scene->id.name+2, sample); 00477 00478 BLI_make_file_string("/", str, btempdir, name); 00479 } 00480 00481 static void render_unique_exr_name(Render *re, char *str, int sample) 00482 { 00483 scene_unique_exr_name(re->scene, str, sample); 00484 } 00485 00486 static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype) 00487 { 00488 const char *typestr= get_pass_name(passtype, 0); 00489 RenderPass *rpass= MEM_callocN(sizeof(RenderPass), typestr); 00490 int rectsize= rr->rectx*rr->recty*channels; 00491 00492 BLI_addtail(&rl->passes, rpass); 00493 rpass->passtype= passtype; 00494 rpass->channels= channels; 00495 rpass->rectx= rl->rectx; 00496 rpass->recty= rl->recty; 00497 00498 if(rr->exrhandle) { 00499 int a; 00500 for(a=0; a<channels; a++) 00501 IMB_exr_add_channel(rr->exrhandle, rl->name, get_pass_name(passtype, a), 0, 0, NULL); 00502 } 00503 else { 00504 float *rect; 00505 int x; 00506 00507 rpass->rect= MEM_mapallocN(sizeof(float)*rectsize, typestr); 00508 00509 if(passtype==SCE_PASS_VECTOR) { 00510 /* initialize to max speed */ 00511 rect= rpass->rect; 00512 for(x= rectsize-1; x>=0; x--) 00513 rect[x]= PASS_VECTOR_MAX; 00514 } 00515 else if(passtype==SCE_PASS_Z) { 00516 rect= rpass->rect; 00517 for(x= rectsize-1; x>=0; x--) 00518 rect[x]= 10e10; 00519 } 00520 } 00521 } 00522 00523 float *RE_RenderLayerGetPass(RenderLayer *rl, int passtype) 00524 { 00525 RenderPass *rpass; 00526 00527 for(rpass=rl->passes.first; rpass; rpass= rpass->next) 00528 if(rpass->passtype== passtype) 00529 return rpass->rect; 00530 return NULL; 00531 } 00532 00533 RenderLayer *RE_GetRenderLayer(RenderResult *rr, const char *name) 00534 { 00535 RenderLayer *rl; 00536 00537 if(rr==NULL) return NULL; 00538 00539 for(rl= rr->layers.first; rl; rl= rl->next) 00540 if(strncmp(rl->name, name, RE_MAXNAME)==0) 00541 return rl; 00542 return NULL; 00543 } 00544 00545 #define RR_USEMEM 0 00546 /* called by main render as well for parts */ 00547 /* will read info from Render *re to define layers */ 00548 /* called in threads */ 00549 /* re->winx,winy is coordinate space of entire image, partrct the part within */ 00550 static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int savebuffers) 00551 { 00552 RenderResult *rr; 00553 RenderLayer *rl; 00554 SceneRenderLayer *srl; 00555 int rectx, recty, nr; 00556 00557 rectx= partrct->xmax - partrct->xmin; 00558 recty= partrct->ymax - partrct->ymin; 00559 00560 if(rectx<=0 || recty<=0) 00561 return NULL; 00562 00563 rr= MEM_callocN(sizeof(RenderResult), "new render result"); 00564 rr->rectx= rectx; 00565 rr->recty= recty; 00566 rr->renrect.xmin= 0; rr->renrect.xmax= rectx-2*crop; 00567 /* crop is one or two extra pixels rendered for filtering, is used for merging and display too */ 00568 rr->crop= crop; 00569 00570 /* tilerect is relative coordinates within render disprect. do not subtract crop yet */ 00571 rr->tilerect.xmin= partrct->xmin - re->disprect.xmin; 00572 rr->tilerect.xmax= partrct->xmax - re->disprect.xmax; 00573 rr->tilerect.ymin= partrct->ymin - re->disprect.ymin; 00574 rr->tilerect.ymax= partrct->ymax - re->disprect.ymax; 00575 00576 if(savebuffers) { 00577 rr->exrhandle= IMB_exr_get_handle(); 00578 } 00579 00580 /* check renderdata for amount of layers */ 00581 for(nr=0, srl= re->r.layers.first; srl; srl= srl->next, nr++) { 00582 00583 if((re->r.scemode & R_SINGLE_LAYER) && nr!=re->r.actlay) 00584 continue; 00585 if(srl->layflag & SCE_LAY_DISABLE) 00586 continue; 00587 00588 rl= MEM_callocN(sizeof(RenderLayer), "new render layer"); 00589 BLI_addtail(&rr->layers, rl); 00590 00591 BLI_strncpy(rl->name, srl->name, sizeof(rl->name)); 00592 rl->lay= srl->lay; 00593 rl->lay_zmask= srl->lay_zmask; 00594 rl->layflag= srl->layflag; 00595 rl->passflag= srl->passflag; // for debugging: srl->passflag|SCE_PASS_RAYHITS; 00596 rl->pass_xor= srl->pass_xor; 00597 rl->light_override= srl->light_override; 00598 rl->mat_override= srl->mat_override; 00599 rl->rectx= rectx; 00600 rl->recty= recty; 00601 00602 if(rr->exrhandle) { 00603 IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R", 0, 0, NULL); 00604 IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G", 0, 0, NULL); 00605 IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B", 0, 0, NULL); 00606 IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A", 0, 0, NULL); 00607 } 00608 else 00609 rl->rectf= MEM_mapallocN(rectx*recty*sizeof(float)*4, "Combined rgba"); 00610 00611 if(srl->passflag & SCE_PASS_Z) 00612 render_layer_add_pass(rr, rl, 1, SCE_PASS_Z); 00613 if(srl->passflag & SCE_PASS_VECTOR) 00614 render_layer_add_pass(rr, rl, 4, SCE_PASS_VECTOR); 00615 if(srl->passflag & SCE_PASS_NORMAL) 00616 render_layer_add_pass(rr, rl, 3, SCE_PASS_NORMAL); 00617 if(srl->passflag & SCE_PASS_UV) 00618 render_layer_add_pass(rr, rl, 3, SCE_PASS_UV); 00619 if(srl->passflag & SCE_PASS_RGBA) 00620 render_layer_add_pass(rr, rl, 4, SCE_PASS_RGBA); 00621 if(srl->passflag & SCE_PASS_EMIT) 00622 render_layer_add_pass(rr, rl, 3, SCE_PASS_EMIT); 00623 if(srl->passflag & SCE_PASS_DIFFUSE) 00624 render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE); 00625 if(srl->passflag & SCE_PASS_SPEC) 00626 render_layer_add_pass(rr, rl, 3, SCE_PASS_SPEC); 00627 if(srl->passflag & SCE_PASS_AO) 00628 render_layer_add_pass(rr, rl, 3, SCE_PASS_AO); 00629 if(srl->passflag & SCE_PASS_ENVIRONMENT) 00630 render_layer_add_pass(rr, rl, 3, SCE_PASS_ENVIRONMENT); 00631 if(srl->passflag & SCE_PASS_INDIRECT) 00632 render_layer_add_pass(rr, rl, 3, SCE_PASS_INDIRECT); 00633 if(srl->passflag & SCE_PASS_SHADOW) 00634 render_layer_add_pass(rr, rl, 3, SCE_PASS_SHADOW); 00635 if(srl->passflag & SCE_PASS_REFLECT) 00636 render_layer_add_pass(rr, rl, 3, SCE_PASS_REFLECT); 00637 if(srl->passflag & SCE_PASS_REFRACT) 00638 render_layer_add_pass(rr, rl, 3, SCE_PASS_REFRACT); 00639 if(srl->passflag & SCE_PASS_INDEXOB) 00640 render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB); 00641 if(srl->passflag & SCE_PASS_INDEXMA) 00642 render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXMA); 00643 if(srl->passflag & SCE_PASS_MIST) 00644 render_layer_add_pass(rr, rl, 1, SCE_PASS_MIST); 00645 if(rl->passflag & SCE_PASS_RAYHITS) 00646 render_layer_add_pass(rr, rl, 4, SCE_PASS_RAYHITS); 00647 00648 } 00649 /* sss, previewrender and envmap don't do layers, so we make a default one */ 00650 if(rr->layers.first==NULL) { 00651 rl= MEM_callocN(sizeof(RenderLayer), "new render layer"); 00652 BLI_addtail(&rr->layers, rl); 00653 00654 rl->rectx= rectx; 00655 rl->recty= recty; 00656 00657 /* duplicate code... */ 00658 if(rr->exrhandle) { 00659 IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R", 0, 0, NULL); 00660 IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G", 0, 0, NULL); 00661 IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B", 0, 0, NULL); 00662 IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A", 0, 0, NULL); 00663 } 00664 else 00665 rl->rectf= MEM_mapallocN(rectx*recty*sizeof(float)*4, "Combined rgba"); 00666 00667 /* note, this has to be in sync with scene.c */ 00668 rl->lay= (1<<20) -1; 00669 rl->layflag= 0x7FFF; /* solid ztra halo strand */ 00670 rl->passflag= SCE_PASS_COMBINED; 00671 00672 re->r.actlay= 0; 00673 } 00674 00675 /* border render; calculate offset for use in compositor. compo is centralized coords */ 00676 rr->xof= re->disprect.xmin + (re->disprect.xmax - re->disprect.xmin)/2 - re->winx/2; 00677 rr->yof= re->disprect.ymin + (re->disprect.ymax - re->disprect.ymin)/2 - re->winy/2; 00678 00679 return rr; 00680 } 00681 00682 static int render_scene_needs_vector(Render *re) 00683 { 00684 SceneRenderLayer *srl; 00685 00686 for(srl= re->scene->r.layers.first; srl; srl= srl->next) 00687 if(!(srl->layflag & SCE_LAY_DISABLE)) 00688 if(srl->passflag & SCE_PASS_VECTOR) 00689 return 1; 00690 00691 return 0; 00692 } 00693 00694 static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize) 00695 { 00696 int y, ofs, copylen, tilex, tiley; 00697 00698 copylen= tilex= rrpart->rectx; 00699 tiley= rrpart->recty; 00700 00701 if(rrpart->crop) { /* filters add pixel extra */ 00702 tile+= pixsize*(rrpart->crop + rrpart->crop*tilex); 00703 00704 copylen= tilex - 2*rrpart->crop; 00705 tiley -= 2*rrpart->crop; 00706 00707 ofs= (rrpart->tilerect.ymin + rrpart->crop)*rr->rectx + (rrpart->tilerect.xmin+rrpart->crop); 00708 target+= pixsize*ofs; 00709 } 00710 else { 00711 ofs= (rrpart->tilerect.ymin*rr->rectx + rrpart->tilerect.xmin); 00712 target+= pixsize*ofs; 00713 } 00714 00715 copylen *= sizeof(float)*pixsize; 00716 tilex *= pixsize; 00717 ofs= pixsize*rr->rectx; 00718 00719 for(y=0; y<tiley; y++) { 00720 memcpy(target, tile, copylen); 00721 target+= ofs; 00722 tile+= tilex; 00723 } 00724 } 00725 00726 /* used when rendering to a full buffer, or when reading the exr part-layer-pass file */ 00727 /* no test happens here if it fits... we also assume layers are in sync */ 00728 /* is used within threads */ 00729 static void merge_render_result(RenderResult *rr, RenderResult *rrpart) 00730 { 00731 RenderLayer *rl, *rlp; 00732 RenderPass *rpass, *rpassp; 00733 00734 for(rl= rr->layers.first, rlp= rrpart->layers.first; rl && rlp; rl= rl->next, rlp= rlp->next) { 00735 00736 /* combined */ 00737 if(rl->rectf && rlp->rectf) 00738 do_merge_tile(rr, rrpart, rl->rectf, rlp->rectf, 4); 00739 00740 /* passes are allocated in sync */ 00741 for(rpass= rl->passes.first, rpassp= rlp->passes.first; rpass && rpassp; rpass= rpass->next, rpassp= rpassp->next) { 00742 do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels); 00743 } 00744 } 00745 } 00746 00747 00748 static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart) 00749 { 00750 RenderLayer *rlp; 00751 RenderPass *rpassp; 00752 int offs, partx, party; 00753 00754 BLI_lock_thread(LOCK_IMAGE); 00755 00756 for(rlp= rrpart->layers.first; rlp; rlp= rlp->next) { 00757 00758 if(rrpart->crop) { /* filters add pixel extra */ 00759 offs= (rrpart->crop + rrpart->crop*rrpart->rectx); 00760 } 00761 else { 00762 offs= 0; 00763 } 00764 00765 /* combined */ 00766 if(rlp->rectf) { 00767 int a, xstride= 4; 00768 for(a=0; a<xstride; a++) 00769 IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(SCE_PASS_COMBINED, a), 00770 xstride, xstride*rrpart->rectx, rlp->rectf+a + xstride*offs); 00771 } 00772 00773 /* passes are allocated in sync */ 00774 for(rpassp= rlp->passes.first; rpassp; rpassp= rpassp->next) { 00775 int a, xstride= rpassp->channels; 00776 for(a=0; a<xstride; a++) 00777 IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a), 00778 xstride, xstride*rrpart->rectx, rpassp->rect+a + xstride*offs); 00779 } 00780 00781 } 00782 00783 party= rrpart->tilerect.ymin + rrpart->crop; 00784 partx= rrpart->tilerect.xmin + rrpart->crop; 00785 IMB_exrtile_write_channels(rr->exrhandle, partx, party, 0); 00786 00787 BLI_unlock_thread(LOCK_IMAGE); 00788 00789 } 00790 00791 static void save_empty_result_tiles(Render *re) 00792 { 00793 RenderPart *pa; 00794 RenderResult *rr; 00795 00796 for(rr= re->result; rr; rr= rr->next) { 00797 IMB_exrtile_clear_channels(rr->exrhandle); 00798 00799 for(pa= re->parts.first; pa; pa= pa->next) { 00800 if(pa->ready==0) { 00801 int party= pa->disprect.ymin - re->disprect.ymin + pa->crop; 00802 int partx= pa->disprect.xmin - re->disprect.xmin + pa->crop; 00803 IMB_exrtile_write_channels(rr->exrhandle, partx, party, 0); 00804 } 00805 } 00806 } 00807 } 00808 00809 00810 /* for passes read from files, these have names stored */ 00811 static char *make_pass_name(RenderPass *rpass, int chan) 00812 { 00813 static char name[16]; 00814 int len; 00815 00816 BLI_strncpy(name, rpass->name, EXR_PASS_MAXNAME); 00817 len= strlen(name); 00818 name[len]= '.'; 00819 name[len+1]= rpass->chan_id[chan]; 00820 name[len+2]= 0; 00821 00822 return name; 00823 } 00824 00825 /* filename already made absolute */ 00826 /* called from within UI, saves both rendered result as a file-read result */ 00827 void RE_WriteRenderResult(RenderResult *rr, const char *filename, int compress) 00828 { 00829 RenderLayer *rl; 00830 RenderPass *rpass; 00831 void *exrhandle= IMB_exr_get_handle(); 00832 00833 BLI_make_existing_file(filename); 00834 00835 /* composite result */ 00836 if(rr->rectf) { 00837 IMB_exr_add_channel(exrhandle, "Composite", "Combined.R", 4, 4*rr->rectx, rr->rectf); 00838 IMB_exr_add_channel(exrhandle, "Composite", "Combined.G", 4, 4*rr->rectx, rr->rectf+1); 00839 IMB_exr_add_channel(exrhandle, "Composite", "Combined.B", 4, 4*rr->rectx, rr->rectf+2); 00840 IMB_exr_add_channel(exrhandle, "Composite", "Combined.A", 4, 4*rr->rectx, rr->rectf+3); 00841 } 00842 00843 /* add layers/passes and assign channels */ 00844 for(rl= rr->layers.first; rl; rl= rl->next) { 00845 00846 /* combined */ 00847 if(rl->rectf) { 00848 int a, xstride= 4; 00849 for(a=0; a<xstride; a++) 00850 IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), 00851 xstride, xstride*rr->rectx, rl->rectf+a); 00852 } 00853 00854 /* passes are allocated in sync */ 00855 for(rpass= rl->passes.first; rpass; rpass= rpass->next) { 00856 int a, xstride= rpass->channels; 00857 for(a=0; a<xstride; a++) { 00858 if(rpass->passtype) 00859 IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), 00860 xstride, xstride*rr->rectx, rpass->rect+a); 00861 else 00862 IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), 00863 xstride, xstride*rr->rectx, rpass->rect+a); 00864 } 00865 } 00866 } 00867 00868 IMB_exr_begin_write(exrhandle, filename, rr->rectx, rr->recty, compress); 00869 00870 IMB_exr_write_channels(exrhandle); 00871 IMB_exr_close(exrhandle); 00872 } 00873 00874 /* callbacks for RE_MultilayerConvert */ 00875 static void *ml_addlayer_cb(void *base, char *str) 00876 { 00877 RenderResult *rr= base; 00878 RenderLayer *rl; 00879 00880 rl= MEM_callocN(sizeof(RenderLayer), "new render layer"); 00881 BLI_addtail(&rr->layers, rl); 00882 00883 BLI_strncpy(rl->name, str, EXR_LAY_MAXNAME); 00884 return rl; 00885 } 00886 static void ml_addpass_cb(void *UNUSED(base), void *lay, char *str, float *rect, int totchan, char *chan_id) 00887 { 00888 RenderLayer *rl= lay; 00889 RenderPass *rpass= MEM_callocN(sizeof(RenderPass), "loaded pass"); 00890 int a; 00891 00892 BLI_addtail(&rl->passes, rpass); 00893 rpass->channels= totchan; 00894 00895 rpass->passtype= passtype_from_name(str); 00896 if(rpass->passtype==0) printf("unknown pass %s\n", str); 00897 rl->passflag |= rpass->passtype; 00898 00899 BLI_strncpy(rpass->name, str, EXR_PASS_MAXNAME); 00900 /* channel id chars */ 00901 for(a=0; a<totchan; a++) 00902 rpass->chan_id[a]= chan_id[a]; 00903 00904 rpass->rect= rect; 00905 } 00906 00907 /* from imbuf, if a handle was returned we convert this to render result */ 00908 RenderResult *RE_MultilayerConvert(void *exrhandle, int rectx, int recty) 00909 { 00910 RenderResult *rr= MEM_callocN(sizeof(RenderResult), "loaded render result"); 00911 RenderLayer *rl; 00912 RenderPass *rpass; 00913 00914 rr->rectx= rectx; 00915 rr->recty= recty; 00916 00917 IMB_exr_multilayer_convert(exrhandle, rr, ml_addlayer_cb, ml_addpass_cb); 00918 00919 for(rl=rr->layers.first; rl; rl=rl->next) { 00920 rl->rectx= rectx; 00921 rl->recty= recty; 00922 00923 for(rpass=rl->passes.first; rpass; rpass=rpass->next) { 00924 rpass->rectx= rectx; 00925 rpass->recty= recty; 00926 } 00927 } 00928 00929 return rr; 00930 } 00931 00932 /* called in end of render, to add names to passes... for UI only */ 00933 static void renderresult_add_names(RenderResult *rr) 00934 { 00935 RenderLayer *rl; 00936 RenderPass *rpass; 00937 00938 for(rl= rr->layers.first; rl; rl= rl->next) 00939 for(rpass= rl->passes.first; rpass; rpass= rpass->next) 00940 BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name)); 00941 } 00942 00943 /* called for reading temp files, and for external engines */ 00944 static int read_render_result_from_file(const char *filename, RenderResult *rr) 00945 { 00946 RenderLayer *rl; 00947 RenderPass *rpass; 00948 void *exrhandle= IMB_exr_get_handle(); 00949 int rectx, recty; 00950 00951 if(IMB_exr_begin_read(exrhandle, filename, &rectx, &recty)==0) { 00952 printf("failed being read %s\n", filename); 00953 IMB_exr_close(exrhandle); 00954 return 0; 00955 } 00956 00957 if(rr == NULL || rectx!=rr->rectx || recty!=rr->recty) { 00958 if(rr) 00959 printf("error in reading render result: dimensions don't match\n"); 00960 else 00961 printf("error in reading render result: NULL result pointer\n"); 00962 IMB_exr_close(exrhandle); 00963 return 0; 00964 } 00965 else { 00966 for(rl= rr->layers.first; rl; rl= rl->next) { 00967 00968 /* combined */ 00969 if(rl->rectf) { 00970 int a, xstride= 4; 00971 for(a=0; a<xstride; a++) 00972 IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), 00973 xstride, xstride*rectx, rl->rectf+a); 00974 } 00975 00976 /* passes are allocated in sync */ 00977 for(rpass= rl->passes.first; rpass; rpass= rpass->next) { 00978 int a, xstride= rpass->channels; 00979 for(a=0; a<xstride; a++) 00980 IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), 00981 xstride, xstride*rectx, rpass->rect+a); 00982 } 00983 00984 } 00985 IMB_exr_read_channels(exrhandle); 00986 renderresult_add_names(rr); 00987 } 00988 00989 IMB_exr_close(exrhandle); 00990 00991 return 1; 00992 } 00993 00994 /* only for temp buffer files, makes exact copy of render result */ 00995 static void read_render_result(Render *re, int sample) 00996 { 00997 char str[FILE_MAX]; 00998 00999 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 01000 01001 RE_FreeRenderResult(re->result); 01002 re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM); 01003 01004 render_unique_exr_name(re, str, sample); 01005 printf("read exr tmp file: %s\n", str); 01006 01007 if(!read_render_result_from_file(str, re->result)) 01008 printf("cannot read: %s\n", str); 01009 01010 BLI_rw_mutex_unlock(&re->resultmutex); 01011 } 01012 01013 /* *************************************************** */ 01014 01015 Render *RE_GetRender(const char *name) 01016 { 01017 Render *re; 01018 01019 /* search for existing renders */ 01020 for(re= RenderGlobal.renderlist.first; re; re= re->next) 01021 if(strncmp(re->name, name, RE_MAXNAME)==0) 01022 break; 01023 01024 return re; 01025 } 01026 01027 /* if you want to know exactly what has been done */ 01028 RenderResult *RE_AcquireResultRead(Render *re) 01029 { 01030 if(re) { 01031 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ); 01032 return re->result; 01033 } 01034 01035 return NULL; 01036 } 01037 01038 RenderResult *RE_AcquireResultWrite(Render *re) 01039 { 01040 if(re) { 01041 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 01042 return re->result; 01043 } 01044 01045 return NULL; 01046 } 01047 01048 void RE_SwapResult(Render *re, RenderResult **rr) 01049 { 01050 /* for keeping render buffers */ 01051 if(re) { 01052 SWAP(RenderResult*, re->result, *rr); 01053 } 01054 } 01055 01056 01057 void RE_ReleaseResult(Render *re) 01058 { 01059 if(re) 01060 BLI_rw_mutex_unlock(&re->resultmutex); 01061 } 01062 01063 /* displist.c util.... */ 01064 Scene *RE_GetScene(Render *re) 01065 { 01066 if(re) 01067 return re->scene; 01068 return NULL; 01069 } 01070 01071 RenderLayer *render_get_active_layer(Render *re, RenderResult *rr) 01072 { 01073 RenderLayer *rl= BLI_findlink(&rr->layers, re->r.actlay); 01074 01075 if(rl) 01076 return rl; 01077 else 01078 return rr->layers.first; 01079 } 01080 01081 01082 /* fill provided result struct with what's currently active or done */ 01083 void RE_AcquireResultImage(Render *re, RenderResult *rr) 01084 { 01085 memset(rr, 0, sizeof(RenderResult)); 01086 01087 if(re) { 01088 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ); 01089 01090 if(re->result) { 01091 RenderLayer *rl; 01092 01093 rr->rectx= re->result->rectx; 01094 rr->recty= re->result->recty; 01095 01096 rr->rectf= re->result->rectf; 01097 rr->rectz= re->result->rectz; 01098 rr->rect32= re->result->rect32; 01099 01100 /* active layer */ 01101 rl= render_get_active_layer(re, re->result); 01102 01103 if(rl) { 01104 if(rr->rectf==NULL) 01105 rr->rectf= rl->rectf; 01106 if(rr->rectz==NULL) 01107 rr->rectz= RE_RenderLayerGetPass(rl, SCE_PASS_Z); 01108 } 01109 01110 rr->have_combined= (re->result->rectf != NULL); 01111 rr->layers= re->result->layers; 01112 } 01113 } 01114 } 01115 01116 void RE_ReleaseResultImage(Render *re) 01117 { 01118 if(re) 01119 BLI_rw_mutex_unlock(&re->resultmutex); 01120 } 01121 01122 /* caller is responsible for allocating rect in correct size! */ 01123 void RE_ResultGet32(Render *re, unsigned int *rect) 01124 { 01125 RenderResult rres; 01126 01127 RE_AcquireResultImage(re, &rres); 01128 01129 if(rres.rect32) 01130 memcpy(rect, rres.rect32, sizeof(int)*rres.rectx*rres.recty); 01131 else if(rres.rectf) { 01132 float *fp= rres.rectf; 01133 int tot= rres.rectx*rres.recty; 01134 char *cp= (char *)rect; 01135 01136 if (re->r.color_mgt_flag & R_COLOR_MANAGEMENT) { 01137 /* Finally convert back to sRGB rendered image */ 01138 for(;tot>0; tot--, cp+=4, fp+=4) { 01139 cp[0] = FTOCHAR(linearrgb_to_srgb(fp[0])); 01140 cp[1] = FTOCHAR(linearrgb_to_srgb(fp[1])); 01141 cp[2] = FTOCHAR(linearrgb_to_srgb(fp[2])); 01142 cp[3] = FTOCHAR(fp[3]); 01143 } 01144 } 01145 else { 01146 /* Color management is off : no conversion necessary */ 01147 for(;tot>0; tot--, cp+=4, fp+=4) { 01148 cp[0] = FTOCHAR(fp[0]); 01149 cp[1] = FTOCHAR(fp[1]); 01150 cp[2] = FTOCHAR(fp[2]); 01151 cp[3] = FTOCHAR(fp[3]); 01152 } 01153 } 01154 01155 } 01156 else 01157 /* else fill with black */ 01158 memset(rect, 0, sizeof(int)*re->rectx*re->recty); 01159 01160 RE_ReleaseResultImage(re); 01161 } 01162 01163 RenderStats *RE_GetStats(Render *re) 01164 { 01165 return &re->i; 01166 } 01167 01168 Render *RE_NewRender(const char *name) 01169 { 01170 Render *re; 01171 01172 /* only one render per name exists */ 01173 re= RE_GetRender(name); 01174 if(re==NULL) { 01175 01176 /* new render data struct */ 01177 re= MEM_callocN(sizeof(Render), "new render"); 01178 BLI_addtail(&RenderGlobal.renderlist, re); 01179 strncpy(re->name, name, RE_MAXNAME); 01180 BLI_rw_mutex_init(&re->resultmutex); 01181 } 01182 01183 RE_InitRenderCB(re); 01184 01185 /* init some variables */ 01186 re->ycor= 1.0f; 01187 01188 return re; 01189 } 01190 01191 /* called for new renders and when finishing rendering so 01192 * we calways have valid callbacks on a render */ 01193 void RE_InitRenderCB(Render *re) 01194 { 01195 /* set default empty callbacks */ 01196 re->display_init= result_nothing; 01197 re->display_clear= result_nothing; 01198 re->display_draw= result_rcti_nothing; 01199 re->progress= float_nothing; 01200 re->test_break= default_break; 01201 if(G.background) 01202 re->stats_draw= stats_background; 01203 else 01204 re->stats_draw= stats_nothing; 01205 /* clear callback handles */ 01206 re->dih= re->dch= re->ddh= re->sdh= re->prh= re->tbh= NULL; 01207 } 01208 01209 /* only call this while you know it will remove the link too */ 01210 void RE_FreeRender(Render *re) 01211 { 01212 BLI_rw_mutex_end(&re->resultmutex); 01213 01214 free_renderdata_tables(re); 01215 free_sample_tables(re); 01216 01217 RE_FreeRenderResult(re->result); 01218 RE_FreeRenderResult(re->pushedresult); 01219 01220 BLI_remlink(&RenderGlobal.renderlist, re); 01221 MEM_freeN(re); 01222 } 01223 01224 /* exit blender */ 01225 void RE_FreeAllRender(void) 01226 { 01227 while(RenderGlobal.renderlist.first) { 01228 RE_FreeRender(RenderGlobal.renderlist.first); 01229 } 01230 } 01231 01232 /* ********* initialize state ******** */ 01233 01234 01235 /* what doesn't change during entire render sequence */ 01236 /* disprect is optional, if NULL it assumes full window render */ 01237 void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer *srl, int winx, int winy, rcti *disprect) 01238 { 01239 re->ok= TRUE; /* maybe flag */ 01240 01241 re->i.starttime= PIL_check_seconds_timer(); 01242 re->r= *rd; /* hardcopy */ 01243 01244 re->winx= winx; 01245 re->winy= winy; 01246 if(disprect) { 01247 re->disprect= *disprect; 01248 re->rectx= disprect->xmax-disprect->xmin; 01249 re->recty= disprect->ymax-disprect->ymin; 01250 } 01251 else { 01252 re->disprect.xmin= re->disprect.ymin= 0; 01253 re->disprect.xmax= winx; 01254 re->disprect.ymax= winy; 01255 re->rectx= winx; 01256 re->recty= winy; 01257 } 01258 01259 if(re->rectx < 2 || re->recty < 2 || (BKE_imtype_is_movie(rd->imtype) && 01260 (re->rectx < 16 || re->recty < 16) )) { 01261 BKE_report(re->reports, RPT_ERROR, "Image too small"); 01262 re->ok= 0; 01263 return; 01264 } 01265 01266 if((re->r.mode & (R_OSA))==0) 01267 re->r.scemode &= ~R_FULL_SAMPLE; 01268 01269 #ifdef WITH_OPENEXR 01270 if(re->r.scemode & R_FULL_SAMPLE) 01271 re->r.scemode |= R_EXR_TILE_FILE; /* enable automatic */ 01272 01273 /* Until use_border is made compatible with save_buffers/full_sample, render without the later instead of not rendering at all.*/ 01274 if(re->r.mode & R_BORDER) 01275 { 01276 re->r.scemode &= ~(R_EXR_TILE_FILE|R_FULL_SAMPLE); 01277 } 01278 01279 #else 01280 /* can't do this without openexr support */ 01281 re->r.scemode &= ~(R_EXR_TILE_FILE|R_FULL_SAMPLE); 01282 #endif 01283 01284 /* fullsample wants uniform osa levels */ 01285 if(source && (re->r.scemode & R_FULL_SAMPLE)) { 01286 /* but, if source has no full sample we disable it */ 01287 if((source->r.scemode & R_FULL_SAMPLE)==0) 01288 re->r.scemode &= ~R_FULL_SAMPLE; 01289 else 01290 re->r.osa= re->osa= source->osa; 01291 } 01292 else { 01293 /* check state variables, osa? */ 01294 if(re->r.mode & (R_OSA)) { 01295 re->osa= re->r.osa; 01296 if(re->osa>16) re->osa= 16; 01297 } 01298 else re->osa= 0; 01299 } 01300 01301 if (srl) { 01302 int index = BLI_findindex(&re->r.layers, srl); 01303 if (index != -1) { 01304 re->r.actlay = index; 01305 re->r.scemode |= R_SINGLE_LAYER; 01306 } 01307 } 01308 01309 /* always call, checks for gamma, gamma tables and jitter too */ 01310 make_sample_tables(re); 01311 01312 /* if preview render, we try to keep old result */ 01313 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 01314 01315 if(re->r.scemode & R_PREVIEWBUTS) { 01316 if(re->result && re->result->rectx==re->rectx && re->result->recty==re->recty); 01317 else { 01318 RE_FreeRenderResult(re->result); 01319 re->result= NULL; 01320 } 01321 } 01322 else { 01323 01324 /* make empty render result, so display callbacks can initialize */ 01325 RE_FreeRenderResult(re->result); 01326 re->result= MEM_callocN(sizeof(RenderResult), "new render result"); 01327 re->result->rectx= re->rectx; 01328 re->result->recty= re->recty; 01329 } 01330 01331 BLI_rw_mutex_unlock(&re->resultmutex); 01332 01333 /* we clip faces with a minimum of 2 pixel boundary outside of image border. see zbuf.c */ 01334 re->clipcrop= 1.0f + 2.0f/(float)(re->winx>re->winy?re->winy:re->winx); 01335 01336 re->mblur_offs = re->field_offs = 0.f; 01337 01338 RE_init_threadcount(re); 01339 } 01340 01341 /* part of external api, not called for regular render pipeline */ 01342 void RE_SetDispRect (struct Render *re, rcti *disprect) 01343 { 01344 re->disprect= *disprect; 01345 re->rectx= disprect->xmax-disprect->xmin; 01346 re->recty= disprect->ymax-disprect->ymin; 01347 01348 /* initialize render result */ 01349 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 01350 01351 RE_FreeRenderResult(re->result); 01352 re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM); 01353 01354 BLI_rw_mutex_unlock(&re->resultmutex); 01355 } 01356 01357 void RE_SetWindow(Render *re, rctf *viewplane, float clipsta, float clipend) 01358 { 01359 /* re->ok flag? */ 01360 01361 re->viewplane= *viewplane; 01362 re->clipsta= clipsta; 01363 re->clipend= clipend; 01364 re->r.mode &= ~R_ORTHO; 01365 01366 perspective_m4( re->winmat,re->viewplane.xmin, re->viewplane.xmax, re->viewplane.ymin, re->viewplane.ymax, re->clipsta, re->clipend); 01367 01368 } 01369 01370 void RE_SetOrtho(Render *re, rctf *viewplane, float clipsta, float clipend) 01371 { 01372 /* re->ok flag? */ 01373 01374 re->viewplane= *viewplane; 01375 re->clipsta= clipsta; 01376 re->clipend= clipend; 01377 re->r.mode |= R_ORTHO; 01378 01379 orthographic_m4( re->winmat,re->viewplane.xmin, re->viewplane.xmax, re->viewplane.ymin, re->viewplane.ymax, re->clipsta, re->clipend); 01380 } 01381 01382 void RE_SetView(Render *re, float mat[][4]) 01383 { 01384 /* re->ok flag? */ 01385 copy_m4_m4(re->viewmat, mat); 01386 invert_m4_m4(re->viewinv, re->viewmat); 01387 } 01388 01389 /* image and movie output has to move to either imbuf or kernel */ 01390 void RE_display_init_cb(Render *re, void *handle, void (*f)(void *handle, RenderResult *rr)) 01391 { 01392 re->display_init= f; 01393 re->dih= handle; 01394 } 01395 void RE_display_clear_cb(Render *re, void *handle, void (*f)(void *handle, RenderResult *rr)) 01396 { 01397 re->display_clear= f; 01398 re->dch= handle; 01399 } 01400 void RE_display_draw_cb(Render *re, void *handle, void (*f)(void *handle, RenderResult *rr, volatile rcti *rect)) 01401 { 01402 re->display_draw= f; 01403 re->ddh= handle; 01404 } 01405 void RE_stats_draw_cb(Render *re, void *handle, void (*f)(void *handle, RenderStats *rs)) 01406 { 01407 re->stats_draw= f; 01408 re->sdh= handle; 01409 } 01410 void RE_progress_cb(Render *re, void *handle, void (*f)(void *handle, float)) 01411 { 01412 re->progress= f; 01413 re->prh= handle; 01414 } 01415 01416 void RE_draw_lock_cb(Render *re, void *handle, void (*f)(void *handle, int i)) 01417 { 01418 re->draw_lock= f; 01419 re->tbh= handle; 01420 } 01421 01422 void RE_test_break_cb(Render *re, void *handle, int (*f)(void *handle)) 01423 { 01424 re->test_break= f; 01425 re->tbh= handle; 01426 } 01427 01428 01429 /* ********* add object data (later) ******** */ 01430 01431 /* object is considered fully prepared on correct time etc */ 01432 /* includes lights */ 01433 void RE_AddObject(Render *UNUSED(re), Object *UNUSED(ob)) 01434 { 01435 01436 } 01437 01438 /* *************************************** */ 01439 01440 static int render_display_draw_enabled(Render *re) 01441 { 01442 /* don't show preprocess for previewrender sss */ 01443 if(re->sss_points) 01444 return !(re->r.scemode & R_PREVIEWBUTS); 01445 else 01446 return 1; 01447 } 01448 01449 /* allocate osa new results for samples */ 01450 static RenderResult *new_full_sample_buffers(Render *re, ListBase *lb, rcti *partrct, int crop) 01451 { 01452 int a; 01453 01454 if(re->osa==0) 01455 return new_render_result(re, partrct, crop, RR_USEMEM); 01456 01457 for(a=0; a<re->osa; a++) { 01458 RenderResult *rr= new_render_result(re, partrct, crop, RR_USEMEM); 01459 BLI_addtail(lb, rr); 01460 rr->sample_nr= a; 01461 } 01462 01463 return lb->first; 01464 } 01465 01466 01467 /* the main thread call, renders an entire part */ 01468 static void *do_part_thread(void *pa_v) 01469 { 01470 RenderPart *pa= pa_v; 01471 01472 /* need to return nicely all parts on esc */ 01473 if(R.test_break(R.tbh)==0) { 01474 01475 if(!R.sss_points && (R.r.scemode & R_FULL_SAMPLE)) 01476 pa->result= new_full_sample_buffers(&R, &pa->fullresult, &pa->disprect, pa->crop); 01477 else 01478 pa->result= new_render_result(&R, &pa->disprect, pa->crop, RR_USEMEM); 01479 01480 if(R.sss_points) 01481 zbufshade_sss_tile(pa); 01482 else if(R.osa) 01483 zbufshadeDA_tile(pa); 01484 else 01485 zbufshade_tile(pa); 01486 01487 /* merge too on break! */ 01488 if(R.result->exrhandle) { 01489 RenderResult *rr, *rrpart; 01490 01491 for(rr= R.result, rrpart= pa->result; rr && rrpart; rr= rr->next, rrpart= rrpart->next) 01492 save_render_result_tile(rr, rrpart); 01493 01494 } 01495 else if(render_display_draw_enabled(&R)) { 01496 /* on break, don't merge in result for preview renders, looks nicer */ 01497 if(R.test_break(R.tbh) && (R.r.scemode & R_PREVIEWBUTS)); 01498 else merge_render_result(R.result, pa->result); 01499 } 01500 } 01501 01502 pa->ready= 1; 01503 01504 return NULL; 01505 } 01506 01507 /* calculus for how much 1 pixel rendered should rotate the 3d geometry */ 01508 /* is not that simple, needs to be corrected for errors of larger viewplane sizes */ 01509 /* called in initrender.c, initparts() and convertblender.c, for speedvectors */ 01510 float panorama_pixel_rot(Render *re) 01511 { 01512 float psize, phi, xfac; 01513 float borderfac= (float)(re->disprect.xmax - re->disprect.xmin) / (float)re->winx; 01514 01515 /* size of 1 pixel mapped to viewplane coords */ 01516 psize= (re->viewplane.xmax-re->viewplane.xmin)/(float)(re->winx); 01517 /* angle of a pixel */ 01518 phi= atan(psize/re->clipsta); 01519 01520 /* correction factor for viewplane shifting, first calculate how much the viewplane angle is */ 01521 xfac= borderfac*((re->viewplane.xmax-re->viewplane.xmin))/(float)re->xparts; 01522 xfac= atan(0.5f*xfac/re->clipsta); 01523 /* and how much the same viewplane angle is wrapped */ 01524 psize= 0.5f*phi*((float)re->partx); 01525 01526 /* the ratio applied to final per-pixel angle */ 01527 phi*= xfac/psize; 01528 01529 return phi; 01530 } 01531 01532 /* call when all parts stopped rendering, to find the next Y slice */ 01533 /* if slice found, it rotates the dbase */ 01534 static RenderPart *find_next_pano_slice(Render *re, int *minx, rctf *viewplane) 01535 { 01536 RenderPart *pa, *best= NULL; 01537 01538 *minx= re->winx; 01539 01540 /* most left part of the non-rendering parts */ 01541 for(pa= re->parts.first; pa; pa= pa->next) { 01542 if(pa->ready==0 && pa->nr==0) { 01543 if(pa->disprect.xmin < *minx) { 01544 best= pa; 01545 *minx= pa->disprect.xmin; 01546 } 01547 } 01548 } 01549 01550 if(best) { 01551 float phi= panorama_pixel_rot(re); 01552 01553 R.panodxp= (re->winx - (best->disprect.xmin + best->disprect.xmax) )/2; 01554 R.panodxv= ((viewplane->xmax-viewplane->xmin)*R.panodxp)/(float)(re->winx); 01555 01556 /* shift viewplane */ 01557 R.viewplane.xmin = viewplane->xmin + R.panodxv; 01558 R.viewplane.xmax = viewplane->xmax + R.panodxv; 01559 RE_SetWindow(re, &R.viewplane, R.clipsta, R.clipend); 01560 copy_m4_m4(R.winmat, re->winmat); 01561 01562 /* rotate database according to part coordinates */ 01563 project_renderdata(re, projectverto, 1, -R.panodxp*phi, 1); 01564 R.panosi= sin(R.panodxp*phi); 01565 R.panoco= cos(R.panodxp*phi); 01566 } 01567 return best; 01568 } 01569 01570 static RenderPart *find_next_part(Render *re, int minx) 01571 { 01572 RenderPart *pa, *best= NULL; 01573 01574 /* long long int's needed because of overflow [#24414] */ 01575 long long int centx=re->winx/2, centy=re->winy/2, tot=1; 01576 long long int mindist= (long long int)re->winx * (long long int)re->winy; 01577 01578 /* find center of rendered parts, image center counts for 1 too */ 01579 for(pa= re->parts.first; pa; pa= pa->next) { 01580 if(pa->ready) { 01581 centx+= (pa->disprect.xmin+pa->disprect.xmax)/2; 01582 centy+= (pa->disprect.ymin+pa->disprect.ymax)/2; 01583 tot++; 01584 } 01585 } 01586 centx/=tot; 01587 centy/=tot; 01588 01589 /* closest of the non-rendering parts */ 01590 for(pa= re->parts.first; pa; pa= pa->next) { 01591 if(pa->ready==0 && pa->nr==0) { 01592 long long int distx= centx - (pa->disprect.xmin+pa->disprect.xmax)/2; 01593 long long int disty= centy - (pa->disprect.ymin+pa->disprect.ymax)/2; 01594 distx= (long long int)sqrt(distx*distx + disty*disty); 01595 if(distx<mindist) { 01596 if(re->r.mode & R_PANORAMA) { 01597 if(pa->disprect.xmin==minx) { 01598 best= pa; 01599 mindist= distx; 01600 } 01601 } 01602 else { 01603 best= pa; 01604 mindist= distx; 01605 } 01606 } 01607 } 01608 } 01609 return best; 01610 } 01611 01612 static void print_part_stats(Render *re, RenderPart *pa) 01613 { 01614 char str[64]; 01615 01616 BLI_snprintf(str, sizeof(str), "%s, Part %d-%d", re->scene->id.name+2, pa->nr, re->i.totpart); 01617 re->i.infostr= str; 01618 re->stats_draw(re->sdh, &re->i); 01619 re->i.infostr= NULL; 01620 } 01621 01622 /* make osa new results for samples */ 01623 static RenderResult *new_full_sample_buffers_exr(Render *re) 01624 { 01625 int a; 01626 01627 for(a=0; a<re->osa; a++) { 01628 RenderResult *rr= new_render_result(re, &re->disprect, 0, 1); 01629 BLI_addtail(&re->fullresult, rr); 01630 rr->sample_nr= a; 01631 } 01632 01633 return re->fullresult.first; 01634 } 01635 01636 static void threaded_tile_processor(Render *re) 01637 { 01638 ListBase threads; 01639 RenderPart *pa, *nextpa; 01640 rctf viewplane= re->viewplane; 01641 int rendering=1, counter= 1, drawtimer=0, hasdrawn, minx=0; 01642 01643 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 01644 01645 /* first step; free the entire render result, make new, and/or prepare exr buffer saving */ 01646 if(re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) { 01647 RE_FreeRenderResult(re->result); 01648 01649 if(re->sss_points && render_display_draw_enabled(re)) 01650 re->result= new_render_result(re, &re->disprect, 0, 0); 01651 else if(re->r.scemode & R_FULL_SAMPLE) 01652 re->result= new_full_sample_buffers_exr(re); 01653 else 01654 re->result= new_render_result(re, &re->disprect, 0, re->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE)); 01655 } 01656 01657 BLI_rw_mutex_unlock(&re->resultmutex); 01658 01659 if(re->result==NULL) 01660 return; 01661 01662 /* warning; no return here without closing exr file */ 01663 01664 initparts(re); 01665 01666 if(re->result->exrhandle) { 01667 RenderResult *rr; 01668 char str[FILE_MAX]; 01669 01670 for(rr= re->result; rr; rr= rr->next) { 01671 render_unique_exr_name(re, str, rr->sample_nr); 01672 01673 printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str); 01674 IMB_exrtile_begin_write(rr->exrhandle, str, 0, rr->rectx, rr->recty, re->partx, re->party); 01675 } 01676 } 01677 01678 BLI_init_threads(&threads, do_part_thread, re->r.threads); 01679 01680 /* assuming no new data gets added to dbase... */ 01681 R= *re; 01682 01683 /* set threadsafe break */ 01684 R.test_break= thread_break; 01685 01686 /* timer loop demands to sleep when no parts are left, so we enter loop with a part */ 01687 if(re->r.mode & R_PANORAMA) 01688 nextpa= find_next_pano_slice(re, &minx, &viewplane); 01689 else 01690 nextpa= find_next_part(re, 0); 01691 01692 while(rendering) { 01693 01694 if(re->test_break(re->tbh)) 01695 PIL_sleep_ms(50); 01696 else if(nextpa && BLI_available_threads(&threads)) { 01697 drawtimer= 0; 01698 nextpa->nr= counter++; /* for nicest part, and for stats */ 01699 nextpa->thread= BLI_available_thread_index(&threads); /* sample index */ 01700 BLI_insert_thread(&threads, nextpa); 01701 01702 nextpa= find_next_part(re, minx); 01703 } 01704 else if(re->r.mode & R_PANORAMA) { 01705 if(nextpa==NULL && BLI_available_threads(&threads)==re->r.threads) 01706 nextpa= find_next_pano_slice(re, &minx, &viewplane); 01707 else { 01708 PIL_sleep_ms(50); 01709 drawtimer++; 01710 } 01711 } 01712 else { 01713 PIL_sleep_ms(50); 01714 drawtimer++; 01715 } 01716 01717 /* check for ready ones to display, and if we need to continue */ 01718 rendering= 0; 01719 hasdrawn= 0; 01720 for(pa= re->parts.first; pa; pa= pa->next) { 01721 if(pa->ready) { 01722 01723 BLI_remove_thread(&threads, pa); 01724 01725 if(pa->result) { 01726 if(render_display_draw_enabled(re)) 01727 re->display_draw(re->ddh, pa->result, NULL); 01728 print_part_stats(re, pa); 01729 01730 free_render_result(&pa->fullresult, pa->result); 01731 pa->result= NULL; 01732 re->i.partsdone++; 01733 re->progress(re->prh, re->i.partsdone / (float)re->i.totpart); 01734 hasdrawn= 1; 01735 } 01736 } 01737 else { 01738 rendering= 1; 01739 if(pa->nr && pa->result && drawtimer>20) { 01740 if(render_display_draw_enabled(re)) 01741 re->display_draw(re->ddh, pa->result, &pa->result->renrect); 01742 hasdrawn= 1; 01743 } 01744 } 01745 } 01746 if(hasdrawn) 01747 drawtimer= 0; 01748 01749 /* on break, wait for all slots to get freed */ 01750 if( (g_break=re->test_break(re->tbh)) && BLI_available_threads(&threads)==re->r.threads) 01751 rendering= 0; 01752 01753 } 01754 01755 if(re->result->exrhandle) { 01756 RenderResult *rr; 01757 01758 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 01759 save_empty_result_tiles(re); 01760 01761 for(rr= re->result; rr; rr= rr->next) { 01762 IMB_exr_close(rr->exrhandle); 01763 rr->exrhandle= NULL; 01764 } 01765 01766 free_render_result(&re->fullresult, re->result); 01767 re->result= NULL; 01768 01769 BLI_rw_mutex_unlock(&re->resultmutex); 01770 01771 read_render_result(re, 0); 01772 } 01773 01774 /* unset threadsafety */ 01775 g_break= 0; 01776 01777 BLI_end_threads(&threads); 01778 freeparts(re); 01779 re->viewplane= viewplane; /* restore viewplane, modified by pano render */ 01780 } 01781 01782 /* currently only called by preview renders and envmap */ 01783 void RE_TileProcessor(Render *re) 01784 { 01785 threaded_tile_processor(re); 01786 } 01787 01788 /* ************ This part uses API, for rendering Blender scenes ********** */ 01789 01790 static int external_render_3d(Render *re, int do_all); 01791 01792 static void do_render_3d(Render *re) 01793 { 01794 /* try external */ 01795 if(external_render_3d(re, 0)) 01796 return; 01797 01798 /* internal */ 01799 01800 // re->cfra= cfra; /* <- unused! */ 01801 re->scene->r.subframe = re->mblur_offs + re->field_offs; 01802 01803 /* lock drawing in UI during data phase */ 01804 if(re->draw_lock) 01805 re->draw_lock(re->dlh, 1); 01806 01807 /* make render verts/faces/halos/lamps */ 01808 if(render_scene_needs_vector(re)) 01809 RE_Database_FromScene_Vectors(re, re->main, re->scene, re->lay); 01810 else 01811 RE_Database_FromScene(re, re->main, re->scene, re->lay, 1); 01812 01813 /* clear UI drawing locks */ 01814 if(re->draw_lock) 01815 re->draw_lock(re->dlh, 0); 01816 01817 threaded_tile_processor(re); 01818 01819 /* do left-over 3d post effects (flares) */ 01820 if(re->flag & R_HALO) 01821 if(!re->test_break(re->tbh)) 01822 add_halo_flare(re); 01823 01824 /* free all render verts etc */ 01825 RE_Database_Free(re); 01826 01827 re->scene->r.subframe = 0.f; 01828 } 01829 01830 /* called by blur loop, accumulate RGBA key alpha */ 01831 static void addblur_rect_key(RenderResult *rr, float *rectf, float *rectf1, float blurfac) 01832 { 01833 float mfac= 1.0f - blurfac; 01834 int a, b, stride= 4*rr->rectx; 01835 int len= stride*sizeof(float); 01836 01837 for(a=0; a<rr->recty; a++) { 01838 if(blurfac==1.0f) { 01839 memcpy(rectf, rectf1, len); 01840 } 01841 else { 01842 float *rf= rectf, *rf1= rectf1; 01843 01844 for( b= rr->rectx; b>0; b--, rf+=4, rf1+=4) { 01845 if(rf1[3]<0.01f) 01846 rf[3]= mfac*rf[3]; 01847 else if(rf[3]<0.01f) { 01848 rf[0]= rf1[0]; 01849 rf[1]= rf1[1]; 01850 rf[2]= rf1[2]; 01851 rf[3]= blurfac*rf1[3]; 01852 } 01853 else { 01854 rf[0]= mfac*rf[0] + blurfac*rf1[0]; 01855 rf[1]= mfac*rf[1] + blurfac*rf1[1]; 01856 rf[2]= mfac*rf[2] + blurfac*rf1[2]; 01857 rf[3]= mfac*rf[3] + blurfac*rf1[3]; 01858 } 01859 } 01860 } 01861 rectf+= stride; 01862 rectf1+= stride; 01863 } 01864 } 01865 01866 /* called by blur loop, accumulate renderlayers */ 01867 static void addblur_rect(RenderResult *rr, float *rectf, float *rectf1, float blurfac, int channels) 01868 { 01869 float mfac= 1.0f - blurfac; 01870 int a, b, stride= channels*rr->rectx; 01871 int len= stride*sizeof(float); 01872 01873 for(a=0; a<rr->recty; a++) { 01874 if(blurfac==1.0f) { 01875 memcpy(rectf, rectf1, len); 01876 } 01877 else { 01878 float *rf= rectf, *rf1= rectf1; 01879 01880 for( b= rr->rectx*channels; b>0; b--, rf++, rf1++) { 01881 rf[0]= mfac*rf[0] + blurfac*rf1[0]; 01882 } 01883 } 01884 rectf+= stride; 01885 rectf1+= stride; 01886 } 01887 } 01888 01889 01890 /* called by blur loop, accumulate renderlayers */ 01891 static void merge_renderresult_blur(RenderResult *rr, RenderResult *brr, float blurfac, int key_alpha) 01892 { 01893 RenderLayer *rl, *rl1; 01894 RenderPass *rpass, *rpass1; 01895 01896 rl1= brr->layers.first; 01897 for(rl= rr->layers.first; rl && rl1; rl= rl->next, rl1= rl1->next) { 01898 01899 /* combined */ 01900 if(rl->rectf && rl1->rectf) { 01901 if(key_alpha) 01902 addblur_rect_key(rr, rl->rectf, rl1->rectf, blurfac); 01903 else 01904 addblur_rect(rr, rl->rectf, rl1->rectf, blurfac, 4); 01905 } 01906 01907 /* passes are allocated in sync */ 01908 rpass1= rl1->passes.first; 01909 for(rpass= rl->passes.first; rpass && rpass1; rpass= rpass->next, rpass1= rpass1->next) { 01910 addblur_rect(rr, rpass->rect, rpass1->rect, blurfac, rpass->channels); 01911 } 01912 } 01913 } 01914 01915 /* main blur loop, can be called by fields too */ 01916 static void do_render_blur_3d(Render *re) 01917 { 01918 RenderResult *rres; 01919 float blurfac; 01920 int blur= re->r.mblur_samples; 01921 01922 /* create accumulation render result */ 01923 rres= new_render_result(re, &re->disprect, 0, RR_USEMEM); 01924 01925 /* do the blur steps */ 01926 while(blur--) { 01927 re->mblur_offs = re->r.blurfac*((float)(re->r.mblur_samples-blur))/(float)re->r.mblur_samples; 01928 01929 re->i.curblur= re->r.mblur_samples-blur; /* stats */ 01930 01931 do_render_3d(re); 01932 01933 blurfac= 1.0f/(float)(re->r.mblur_samples-blur); 01934 01935 merge_renderresult_blur(rres, re->result, blurfac, re->r.alphamode & R_ALPHAKEY); 01936 if(re->test_break(re->tbh)) break; 01937 } 01938 01939 /* swap results */ 01940 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 01941 RE_FreeRenderResult(re->result); 01942 re->result= rres; 01943 BLI_rw_mutex_unlock(&re->resultmutex); 01944 01945 re->mblur_offs = 0.0f; 01946 re->i.curblur= 0; /* stats */ 01947 01948 /* weak... the display callback wants an active renderlayer pointer... */ 01949 re->result->renlay= render_get_active_layer(re, re->result); 01950 re->display_draw(re->ddh, re->result, NULL); 01951 } 01952 01953 01954 /* function assumes rectf1 and rectf2 to be half size of rectf */ 01955 static void interleave_rect(RenderResult *rr, float *rectf, float *rectf1, float *rectf2, int channels) 01956 { 01957 int a, stride= channels*rr->rectx; 01958 int len= stride*sizeof(float); 01959 01960 for(a=0; a<rr->recty; a+=2) { 01961 memcpy(rectf, rectf1, len); 01962 rectf+= stride; 01963 rectf1+= stride; 01964 memcpy(rectf, rectf2, len); 01965 rectf+= stride; 01966 rectf2+= stride; 01967 } 01968 } 01969 01970 /* merge render results of 2 fields */ 01971 static void merge_renderresult_fields(RenderResult *rr, RenderResult *rr1, RenderResult *rr2) 01972 { 01973 RenderLayer *rl, *rl1, *rl2; 01974 RenderPass *rpass, *rpass1, *rpass2; 01975 01976 rl1= rr1->layers.first; 01977 rl2= rr2->layers.first; 01978 for(rl= rr->layers.first; rl && rl1 && rl2; rl= rl->next, rl1= rl1->next, rl2= rl2->next) { 01979 01980 /* combined */ 01981 if(rl->rectf && rl1->rectf && rl2->rectf) 01982 interleave_rect(rr, rl->rectf, rl1->rectf, rl2->rectf, 4); 01983 01984 /* passes are allocated in sync */ 01985 rpass1= rl1->passes.first; 01986 rpass2= rl2->passes.first; 01987 for(rpass= rl->passes.first; rpass && rpass1 && rpass2; rpass= rpass->next, rpass1= rpass1->next, rpass2= rpass2->next) { 01988 interleave_rect(rr, rpass->rect, rpass1->rect, rpass2->rect, rpass->channels); 01989 } 01990 } 01991 } 01992 01993 01994 /* interleaves 2 frames */ 01995 static void do_render_fields_3d(Render *re) 01996 { 01997 Object *camera= RE_GetCamera(re); 01998 RenderResult *rr1, *rr2= NULL; 01999 02000 /* no render result was created, we can safely halve render y */ 02001 re->winy /= 2; 02002 re->recty /= 2; 02003 re->disprect.ymin /= 2; 02004 re->disprect.ymax /= 2; 02005 02006 re->i.curfield= 1; /* stats */ 02007 02008 /* first field, we have to call camera routine for correct aspect and subpixel offset */ 02009 RE_SetCamera(re, camera); 02010 if(re->r.mode & R_MBLUR && (re->r.scemode & R_FULL_SAMPLE)==0) 02011 do_render_blur_3d(re); 02012 else 02013 do_render_3d(re); 02014 02015 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 02016 rr1= re->result; 02017 re->result= NULL; 02018 BLI_rw_mutex_unlock(&re->resultmutex); 02019 02020 /* second field */ 02021 if(!re->test_break(re->tbh)) { 02022 02023 re->i.curfield= 2; /* stats */ 02024 02025 re->flag |= R_SEC_FIELD; 02026 if((re->r.mode & R_FIELDSTILL)==0) { 02027 re->field_offs = 0.5f; 02028 } 02029 RE_SetCamera(re, camera); 02030 if(re->r.mode & R_MBLUR && (re->r.scemode & R_FULL_SAMPLE)==0) 02031 do_render_blur_3d(re); 02032 else 02033 do_render_3d(re); 02034 re->flag &= ~R_SEC_FIELD; 02035 02036 re->field_offs = 0.0f; 02037 02038 rr2= re->result; 02039 } 02040 02041 /* allocate original height new buffers */ 02042 re->winy *= 2; 02043 re->recty *= 2; 02044 re->disprect.ymin *= 2; 02045 re->disprect.ymax *= 2; 02046 02047 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 02048 re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM); 02049 02050 if(rr2) { 02051 if(re->r.mode & R_ODDFIELD) 02052 merge_renderresult_fields(re->result, rr2, rr1); 02053 else 02054 merge_renderresult_fields(re->result, rr1, rr2); 02055 02056 RE_FreeRenderResult(rr2); 02057 } 02058 02059 RE_FreeRenderResult(rr1); 02060 02061 re->i.curfield= 0; /* stats */ 02062 02063 /* weak... the display callback wants an active renderlayer pointer... */ 02064 re->result->renlay= render_get_active_layer(re, re->result); 02065 02066 BLI_rw_mutex_unlock(&re->resultmutex); 02067 02068 re->display_draw(re->ddh, re->result, NULL); 02069 } 02070 02071 /* main render routine, no compositing */ 02072 static void do_render_fields_blur_3d(Render *re) 02073 { 02074 Object *camera= RE_GetCamera(re); 02075 /* also check for camera here */ 02076 if(camera == NULL) { 02077 printf("ERROR: Cannot render, no camera\n"); 02078 G.afbreek= 1; 02079 return; 02080 } 02081 02082 /* now use renderdata and camera to set viewplane */ 02083 RE_SetCamera(re, camera); 02084 02085 if(re->r.mode & R_FIELDS) 02086 do_render_fields_3d(re); 02087 else if(re->r.mode & R_MBLUR && (re->r.scemode & R_FULL_SAMPLE)==0) 02088 do_render_blur_3d(re); 02089 else 02090 do_render_3d(re); 02091 02092 /* when border render, check if we have to insert it in black */ 02093 if(re->result) { 02094 if(re->r.mode & R_BORDER) { 02095 if((re->r.mode & R_CROP)==0) { 02096 RenderResult *rres; 02097 02098 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 02099 02100 /* sub-rect for merge call later on */ 02101 re->result->tilerect= re->disprect; 02102 02103 /* this copying sequence could become function? */ 02104 /* weak is: it chances disprect from border */ 02105 re->disprect.xmin= re->disprect.ymin= 0; 02106 re->disprect.xmax= re->winx; 02107 re->disprect.ymax= re->winy; 02108 re->rectx= re->winx; 02109 re->recty= re->winy; 02110 02111 rres= new_render_result(re, &re->disprect, 0, RR_USEMEM); 02112 02113 merge_render_result(rres, re->result); 02114 RE_FreeRenderResult(re->result); 02115 re->result= rres; 02116 02117 /* weak... the display callback wants an active renderlayer pointer... */ 02118 re->result->renlay= render_get_active_layer(re, re->result); 02119 02120 BLI_rw_mutex_unlock(&re->resultmutex); 02121 02122 re->display_init(re->dih, re->result); 02123 re->display_draw(re->ddh, re->result, NULL); 02124 } 02125 else { 02126 /* set offset (again) for use in compositor, disprect was manipulated. */ 02127 re->result->xof= 0; 02128 re->result->yof= 0; 02129 } 02130 } 02131 } 02132 } 02133 02134 02135 /* within context of current Render *re, render another scene. 02136 it uses current render image size and disprect, but doesn't execute composite 02137 */ 02138 static void render_scene(Render *re, Scene *sce, int cfra) 02139 { 02140 Render *resc= RE_NewRender(sce->id.name); 02141 int winx= re->winx, winy= re->winy; 02142 02143 sce->r.cfra= cfra; 02144 02145 scene_camera_switch_update(sce); 02146 02147 /* exception: scene uses own size (unfinished code) */ 02148 if(0) { 02149 winx= (sce->r.size*sce->r.xsch)/100; 02150 winy= (sce->r.size*sce->r.ysch)/100; 02151 } 02152 02153 /* initial setup */ 02154 RE_InitState(resc, re, &sce->r, NULL, winx, winy, &re->disprect); 02155 02156 /* still unsure entity this... */ 02157 resc->main= re->main; 02158 resc->scene= sce; 02159 resc->lay= sce->lay; 02160 02161 /* ensure scene has depsgraph, base flags etc OK */ 02162 set_scene_bg(re->main, sce); 02163 02164 /* copy callbacks */ 02165 resc->display_draw= re->display_draw; 02166 resc->ddh= re->ddh; 02167 resc->test_break= re->test_break; 02168 resc->tbh= re->tbh; 02169 resc->stats_draw= re->stats_draw; 02170 resc->sdh= re->sdh; 02171 02172 do_render_fields_blur_3d(resc); 02173 } 02174 02175 /* helper call to detect if this scene needs a render, or if there's a any render layer to render */ 02176 static int composite_needs_render(Scene *sce, int this_scene) 02177 { 02178 bNodeTree *ntree= sce->nodetree; 02179 bNode *node; 02180 02181 if(ntree==NULL) return 1; 02182 if(sce->use_nodes==0) return 1; 02183 if((sce->r.scemode & R_DOCOMP)==0) return 1; 02184 02185 for(node= ntree->nodes.first; node; node= node->next) { 02186 if(node->type==CMP_NODE_R_LAYERS) 02187 if(this_scene==0 || node->id==NULL || node->id==&sce->id) 02188 return 1; 02189 } 02190 return 0; 02191 } 02192 02193 static void tag_scenes_for_render(Render *re) 02194 { 02195 bNode *node; 02196 Scene *sce; 02197 02198 for(sce= re->main->scene.first; sce; sce= sce->id.next) 02199 sce->id.flag &= ~LIB_DOIT; 02200 02201 if(RE_GetCamera(re) && composite_needs_render(re->scene, 1)) 02202 re->scene->id.flag |= LIB_DOIT; 02203 02204 if(re->scene->nodetree==NULL) return; 02205 02206 /* check for render-layers nodes using other scenes, we tag them LIB_DOIT */ 02207 for(node= re->scene->nodetree->nodes.first; node; node= node->next) { 02208 if(node->type==CMP_NODE_R_LAYERS) { 02209 if(node->id) { 02210 if(node->id != (ID *)re->scene) 02211 node->id->flag |= LIB_DOIT; 02212 } 02213 } 02214 } 02215 02216 } 02217 02218 static void ntree_render_scenes(Render *re) 02219 { 02220 bNode *node; 02221 int cfra= re->scene->r.cfra; 02222 int restore_scene= 0; 02223 02224 if(re->scene->nodetree==NULL) return; 02225 02226 tag_scenes_for_render(re); 02227 02228 /* now foreach render-result node tagged we do a full render */ 02229 /* results are stored in a way compisitor will find it */ 02230 for(node= re->scene->nodetree->nodes.first; node; node= node->next) { 02231 if(node->type==CMP_NODE_R_LAYERS) { 02232 if(node->id && node->id != (ID *)re->scene) { 02233 if(node->id->flag & LIB_DOIT) { 02234 Scene *scene = (Scene*)node->id; 02235 02236 render_scene(re, scene, cfra); 02237 restore_scene= (scene != re->scene); 02238 node->id->flag &= ~LIB_DOIT; 02239 02240 NodeTagChanged(re->scene->nodetree, node); 02241 } 02242 } 02243 } 02244 } 02245 02246 /* restore scene if we rendered another last */ 02247 if(restore_scene) 02248 set_scene_bg(re->main, re->scene); 02249 } 02250 02251 /* bad call... need to think over proper method still */ 02252 static void render_composit_stats(void *UNUSED(arg), char *str) 02253 { 02254 R.i.infostr= str; 02255 R.stats_draw(R.sdh, &R.i); 02256 R.i.infostr= NULL; 02257 } 02258 02259 02260 /* reads all buffers, calls optional composite, merges in first result->rectf */ 02261 static void do_merge_fullsample(Render *re, bNodeTree *ntree) 02262 { 02263 float *rectf, filt[3][3]; 02264 int sample; 02265 02266 /* interaction callbacks */ 02267 if(ntree) { 02268 ntree->stats_draw= render_composit_stats; 02269 ntree->test_break= re->test_break; 02270 ntree->progress= re->progress; 02271 ntree->sdh= re->sdh; 02272 ntree->tbh= re->tbh; 02273 ntree->prh= re->prh; 02274 } 02275 02276 /* filtmask needs it */ 02277 R= *re; 02278 02279 /* we accumulate in here */ 02280 rectf= MEM_mapallocN(re->rectx*re->recty*sizeof(float)*4, "fullsample rgba"); 02281 02282 for(sample=0; sample<re->r.osa; sample++) { 02283 Render *re1; 02284 RenderResult rres; 02285 int x, y, mask; 02286 02287 /* enable full sample print */ 02288 R.i.curfsa= sample+1; 02289 02290 /* set all involved renders on the samplebuffers (first was done by render itself, but needs tagged) */ 02291 /* also function below assumes this */ 02292 02293 tag_scenes_for_render(re); 02294 for(re1= RenderGlobal.renderlist.first; re1; re1= re1->next) { 02295 if(re1->scene->id.flag & LIB_DOIT) { 02296 if(re1->r.scemode & R_FULL_SAMPLE) { 02297 if(sample) 02298 read_render_result(re1, sample); 02299 ntreeCompositTagRender(re1->scene); /* ensure node gets exec to put buffers on stack */ 02300 } 02301 } 02302 } 02303 02304 /* composite */ 02305 if(ntree) { 02306 ntreeCompositTagRender(re->scene); 02307 ntreeCompositTagAnimated(ntree); 02308 02309 ntreeCompositExecTree(ntree, &re->r, G.background==0); 02310 } 02311 02312 /* ensure we get either composited result or the active layer */ 02313 RE_AcquireResultImage(re, &rres); 02314 02315 /* accumulate with filter, and clip */ 02316 mask= (1<<sample); 02317 mask_array(mask, filt); 02318 02319 for(y=0; y<re->recty; y++) { 02320 float *rf= rectf + 4*y*re->rectx; 02321 float *col= rres.rectf + 4*y*re->rectx; 02322 02323 for(x=0; x<re->rectx; x++, rf+=4, col+=4) { 02324 /* clamping to 1.0 is needed for correct AA */ 02325 if(col[0]<0.0f) col[0]=0.0f; else if(col[0] > 1.0f) col[0]= 1.0f; 02326 if(col[1]<0.0f) col[1]=0.0f; else if(col[1] > 1.0f) col[1]= 1.0f; 02327 if(col[2]<0.0f) col[2]=0.0f; else if(col[2] > 1.0f) col[2]= 1.0f; 02328 02329 add_filt_fmask_coord(filt, col, rf, re->rectx, re->recty, x, y); 02330 } 02331 } 02332 02333 RE_ReleaseResultImage(re); 02334 02335 /* show stuff */ 02336 if(sample!=re->osa-1) { 02337 /* weak... the display callback wants an active renderlayer pointer... */ 02338 re->result->renlay= render_get_active_layer(re, re->result); 02339 re->display_draw(re->ddh, re->result, NULL); 02340 } 02341 02342 if(re->test_break(re->tbh)) 02343 break; 02344 } 02345 02346 /* clear interaction callbacks */ 02347 if(ntree) { 02348 ntree->stats_draw= NULL; 02349 ntree->test_break= NULL; 02350 ntree->progress= NULL; 02351 ntree->tbh= ntree->sdh= ntree->prh= NULL; 02352 } 02353 02354 /* disable full sample print */ 02355 R.i.curfsa= 0; 02356 02357 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 02358 if(re->result->rectf) 02359 MEM_freeN(re->result->rectf); 02360 re->result->rectf= rectf; 02361 BLI_rw_mutex_unlock(&re->resultmutex); 02362 } 02363 02364 /* called externally, via compositor */ 02365 void RE_MergeFullSample(Render *re, Main *bmain, Scene *sce, bNodeTree *ntree) 02366 { 02367 Scene *scene; 02368 bNode *node; 02369 02370 /* default start situation */ 02371 G.afbreek= 0; 02372 02373 re->main= bmain; 02374 re->scene= sce; 02375 02376 /* first call RE_ReadRenderResult on every renderlayer scene. this creates Render structs */ 02377 02378 /* tag scenes unread */ 02379 for(scene= re->main->scene.first; scene; scene= scene->id.next) 02380 scene->id.flag |= LIB_DOIT; 02381 02382 for(node= ntree->nodes.first; node; node= node->next) { 02383 if(node->type==CMP_NODE_R_LAYERS) { 02384 Scene *nodescene= (Scene *)node->id; 02385 02386 if(nodescene==NULL) nodescene= sce; 02387 if(nodescene->id.flag & LIB_DOIT) { 02388 nodescene->r.mode |= R_OSA; /* render struct needs tables */ 02389 RE_ReadRenderResult(sce, nodescene); 02390 nodescene->id.flag &= ~LIB_DOIT; 02391 } 02392 } 02393 } 02394 02395 /* own render result should be read/allocated */ 02396 if(re->scene->id.flag & LIB_DOIT) { 02397 RE_ReadRenderResult(re->scene, re->scene); 02398 re->scene->id.flag &= ~LIB_DOIT; 02399 } 02400 02401 /* and now we can draw (result is there) */ 02402 re->display_init(re->dih, re->result); 02403 re->display_clear(re->dch, re->result); 02404 02405 do_merge_fullsample(re, ntree); 02406 } 02407 02408 /* returns fully composited render-result on given time step (in RenderData) */ 02409 static void do_render_composite_fields_blur_3d(Render *re) 02410 { 02411 bNodeTree *ntree= re->scene->nodetree; 02412 int update_newframe=0; 02413 02414 /* INIT seeding, compositor can use random texture */ 02415 BLI_srandom(re->r.cfra); 02416 02417 if(composite_needs_render(re->scene, 1)) { 02418 /* save memory... free all cached images */ 02419 ntreeFreeCache(ntree); 02420 02421 do_render_fields_blur_3d(re); 02422 } 02423 else { 02424 /* ensure new result gets added, like for regular renders */ 02425 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 02426 02427 RE_FreeRenderResult(re->result); 02428 re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM); 02429 02430 BLI_rw_mutex_unlock(&re->resultmutex); 02431 02432 /* scene render process already updates animsys */ 02433 update_newframe = 1; 02434 } 02435 02436 /* swap render result */ 02437 if(re->r.scemode & R_SINGLE_LAYER) 02438 pop_render_result(re); 02439 02440 if(!re->test_break(re->tbh)) { 02441 02442 if(ntree) { 02443 ntreeCompositTagRender(re->scene); 02444 ntreeCompositTagAnimated(ntree); 02445 } 02446 02447 if(ntree && re->r.scemode & R_DOCOMP) { 02448 /* checks if there are render-result nodes that need scene */ 02449 if((re->r.scemode & R_SINGLE_LAYER)==0) 02450 ntree_render_scenes(re); 02451 02452 if(!re->test_break(re->tbh)) { 02453 ntree->stats_draw= render_composit_stats; 02454 ntree->test_break= re->test_break; 02455 ntree->progress= re->progress; 02456 ntree->sdh= re->sdh; 02457 ntree->tbh= re->tbh; 02458 ntree->prh= re->prh; 02459 02460 /* in case it was never initialized */ 02461 R.sdh= re->sdh; 02462 R.stats_draw= re->stats_draw; 02463 02464 if (update_newframe) 02465 scene_update_for_newframe(re->main, re->scene, re->lay); 02466 02467 if(re->r.scemode & R_FULL_SAMPLE) 02468 do_merge_fullsample(re, ntree); 02469 else { 02470 ntreeCompositExecTree(ntree, &re->r, G.background==0); 02471 } 02472 02473 ntree->stats_draw= NULL; 02474 ntree->test_break= NULL; 02475 ntree->progress= NULL; 02476 ntree->tbh= ntree->sdh= ntree->prh= NULL; 02477 } 02478 } 02479 else if(re->r.scemode & R_FULL_SAMPLE) 02480 do_merge_fullsample(re, NULL); 02481 } 02482 02483 /* weak... the display callback wants an active renderlayer pointer... */ 02484 re->result->renlay= render_get_active_layer(re, re->result); 02485 re->display_draw(re->ddh, re->result, NULL); 02486 } 02487 02488 static void renderresult_stampinfo(Render *re) 02489 { 02490 RenderResult rres; 02491 02492 /* this is the basic trick to get the displayed float or char rect from render result */ 02493 RE_AcquireResultImage(re, &rres); 02494 BKE_stamp_buf(re->scene, RE_GetCamera(re), (unsigned char *)rres.rect32, rres.rectf, rres.rectx, rres.recty, 4); 02495 RE_ReleaseResultImage(re); 02496 } 02497 02498 static int seq_render_active(Render *re) 02499 { 02500 Editing *ed; 02501 Sequence *seq; 02502 02503 ed = re->scene->ed; 02504 02505 if (!(re->r.scemode & R_DOSEQ) || !ed || !ed->seqbase.first) 02506 return 0; 02507 02508 for (seq= ed->seqbase.first; seq; seq= seq->next) { 02509 if (seq->type != SEQ_SOUND) 02510 return 1; 02511 } 02512 02513 return 0; 02514 } 02515 02516 static void do_render_seq(Render * re) 02517 { 02518 static int recurs_depth = 0; 02519 struct ImBuf *ibuf; 02520 RenderResult *rr; /* don't assign re->result here as it might change during give_ibuf_seq */ 02521 int cfra = re->r.cfra; 02522 SeqRenderData context; 02523 02524 re->i.cfra= cfra; 02525 02526 if(recurs_depth==0) { 02527 /* otherwise sequencer animation isnt updated */ 02528 BKE_animsys_evaluate_all_animation(re->main, (float)cfra); // XXX, was BKE_curframe(re->scene) 02529 } 02530 02531 recurs_depth++; 02532 02533 context = seq_new_render_data(re->main, re->scene, 02534 re->result->rectx, re->result->recty, 02535 100); 02536 02537 ibuf = give_ibuf_seq(context, cfra, 0); 02538 02539 recurs_depth--; 02540 02541 rr = re->result; 02542 02543 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 02544 02545 if(ibuf) { 02546 if(ibuf->rect_float) { 02547 if (!rr->rectf) 02548 rr->rectf= MEM_mallocN(4*sizeof(float)*rr->rectx*rr->recty, "render_seq rectf"); 02549 02550 /* color management: when off ensure rectf is non-lin, since thats what the internal 02551 * render engine delivers */ 02552 if(re->r.color_mgt_flag & R_COLOR_MANAGEMENT) { 02553 if(ibuf->profile == IB_PROFILE_LINEAR_RGB) 02554 memcpy(rr->rectf, ibuf->rect_float, 4*sizeof(float)*rr->rectx*rr->recty); 02555 else 02556 srgb_to_linearrgb_rgba_rgba_buf(rr->rectf, ibuf->rect_float, rr->rectx*rr->recty); 02557 02558 } 02559 else { 02560 if(ibuf->profile != IB_PROFILE_LINEAR_RGB) 02561 memcpy(rr->rectf, ibuf->rect_float, 4*sizeof(float)*rr->rectx*rr->recty); 02562 else 02563 linearrgb_to_srgb_rgba_rgba_buf(rr->rectf, ibuf->rect_float, rr->rectx*rr->recty); 02564 } 02565 02566 /* TSK! Since sequence render doesn't free the *rr render result, the old rect32 02567 can hang around when sequence render has rendered a 32 bits one before */ 02568 if(rr->rect32) { 02569 MEM_freeN(rr->rect32); 02570 rr->rect32= NULL; 02571 } 02572 } 02573 else if(ibuf->rect) { 02574 if (!rr->rect32) 02575 rr->rect32= MEM_mallocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect"); 02576 02577 memcpy(rr->rect32, ibuf->rect, 4*rr->rectx*rr->recty); 02578 02579 /* if (ibuf->zbuf) { */ 02580 /* if (R.rectz) freeN(R.rectz); */ 02581 /* R.rectz = BLI_dupallocN(ibuf->zbuf); */ 02582 /* } */ 02583 02584 /* Same things as above, old rectf can hang around from previous render. */ 02585 if(rr->rectf) { 02586 MEM_freeN(rr->rectf); 02587 rr->rectf= NULL; 02588 } 02589 } 02590 02591 if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */ 02592 Editing * ed = re->scene->ed; 02593 if (ed) { 02594 free_imbuf_seq(re->scene, &ed->seqbase, TRUE, TRUE); 02595 } 02596 } 02597 IMB_freeImBuf(ibuf); 02598 } 02599 else { 02600 /* render result is delivered empty in most cases, nevertheless we handle all cases */ 02601 if (rr->rectf) 02602 memset(rr->rectf, 0, 4*sizeof(float)*rr->rectx*rr->recty); 02603 else if (rr->rect32) 02604 memset(rr->rect32, 0, 4*rr->rectx*rr->recty); 02605 else 02606 rr->rect32= MEM_callocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect"); 02607 } 02608 02609 BLI_rw_mutex_unlock(&re->resultmutex); 02610 02611 /* just in case this flag went missing at some point */ 02612 re->r.scemode |= R_DOSEQ; 02613 } 02614 02615 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 02616 02617 /* main loop: doing sequence + fields + blur + 3d render + compositing */ 02618 static void do_render_all_options(Render *re) 02619 { 02620 scene_camera_switch_update(re->scene); 02621 02622 re->i.starttime= PIL_check_seconds_timer(); 02623 02624 /* ensure no images are in memory from previous animated sequences */ 02625 BKE_image_all_free_anim_ibufs(re->r.cfra); 02626 02627 if(external_render_3d(re, 1)) { 02628 /* in this case external render overrides all */ 02629 } 02630 else if(seq_render_active(re)) { 02631 /* note: do_render_seq() frees rect32 when sequencer returns float images */ 02632 if(!re->test_break(re->tbh)) 02633 do_render_seq(re); 02634 02635 re->stats_draw(re->sdh, &re->i); 02636 re->display_draw(re->ddh, re->result, NULL); 02637 } 02638 else { 02639 do_render_composite_fields_blur_3d(re); 02640 } 02641 02642 /* for UI only */ 02643 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 02644 renderresult_add_names(re->result); 02645 BLI_rw_mutex_unlock(&re->resultmutex); 02646 02647 re->i.lastframetime= PIL_check_seconds_timer()- re->i.starttime; 02648 02649 re->stats_draw(re->sdh, &re->i); 02650 02651 /* stamp image info here */ 02652 if((re->r.stamp & R_STAMP_ALL) && (re->r.stamp & R_STAMP_DRAW)) { 02653 renderresult_stampinfo(re); 02654 re->display_draw(re->ddh, re->result, NULL); 02655 } 02656 } 02657 02658 static int check_valid_camera(Scene *scene, Object *camera_override) 02659 { 02660 int check_comp= 1; 02661 02662 if (camera_override == NULL && scene->camera == NULL) 02663 scene->camera= scene_find_camera(scene); 02664 02665 if(scene->r.scemode&R_DOSEQ) { 02666 if(scene->ed) { 02667 Sequence *seq= scene->ed->seqbase.first; 02668 02669 check_comp= 0; 02670 02671 while(seq) { 02672 if(seq->type == SEQ_SCENE) { 02673 if(!seq->scene_camera) { 02674 if(!seq->scene->camera && !scene_find_camera(seq->scene)) { 02675 if(seq->scene == scene) { 02676 /* for current scene camera could be unneeded due to compisite nodes */ 02677 check_comp= 1; 02678 } else { 02679 /* for other scenes camera is necessary */ 02680 return 0; 02681 } 02682 } 02683 } 02684 } 02685 02686 seq= seq->next; 02687 } 02688 } 02689 } 02690 02691 if(check_comp) { /* no sequencer or sequencer depends on compositor */ 02692 if(scene->r.scemode&R_DOCOMP && scene->use_nodes) { 02693 bNode *node= scene->nodetree->nodes.first; 02694 02695 while(node) { 02696 if(node->type == CMP_NODE_R_LAYERS) { 02697 Scene *sce= node->id ? (Scene*)node->id : scene; 02698 02699 if(!sce->camera && !scene_find_camera(sce)) { 02700 /* all render layers nodes need camera */ 02701 return 0; 02702 } 02703 } 02704 02705 node= node->next; 02706 } 02707 } else { 02708 return (camera_override != NULL || scene->camera != NULL); 02709 } 02710 } 02711 02712 return 1; 02713 } 02714 02715 int RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *reports) 02716 { 02717 SceneRenderLayer *srl; 02718 02719 if(scene->r.mode & R_BORDER) { 02720 if(scene->r.border.xmax <= scene->r.border.xmin || 02721 scene->r.border.ymax <= scene->r.border.ymin) { 02722 BKE_report(reports, RPT_ERROR, "No border area selected."); 02723 return 0; 02724 } 02725 } 02726 02727 if(scene->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE)) { 02728 char str[FILE_MAX]; 02729 02730 scene_unique_exr_name(scene, str, 0); 02731 02732 if (BLI_is_writable(str)==0) { 02733 BKE_report(reports, RPT_ERROR, "Can not save render buffers, check the temp default path"); 02734 return 0; 02735 } 02736 02737 /* no fullsample and edge */ 02738 if((scene->r.scemode & R_FULL_SAMPLE) && (scene->r.mode & R_EDGE)) { 02739 BKE_report(reports, RPT_ERROR, "Full Sample doesn't support Edge Enhance"); 02740 return 0; 02741 } 02742 02743 } 02744 else 02745 scene->r.scemode &= ~R_FULL_SAMPLE; /* clear to be sure */ 02746 02747 if(scene->r.scemode & R_DOCOMP) { 02748 if(scene->use_nodes) { 02749 bNodeTree *ntree= scene->nodetree; 02750 bNode *node; 02751 02752 if(ntree==NULL) { 02753 BKE_report(reports, RPT_ERROR, "No Nodetree in Scene"); 02754 return 0; 02755 } 02756 02757 for(node= ntree->nodes.first; node; node= node->next) 02758 if(node->type==CMP_NODE_COMPOSITE) 02759 break; 02760 02761 if(node==NULL) { 02762 BKE_report(reports, RPT_ERROR, "No Render Output Node in Scene"); 02763 return 0; 02764 } 02765 02766 if(scene->r.scemode & R_FULL_SAMPLE) { 02767 if(composite_needs_render(scene, 0)==0) { 02768 BKE_report(reports, RPT_ERROR, "Full Sample AA not supported without 3d rendering"); 02769 return 0; 02770 } 02771 } 02772 } 02773 } 02774 02775 /* check valid camera, without camera render is OK (compo, seq) */ 02776 if(!check_valid_camera(scene, camera_override)) { 02777 BKE_report(reports, RPT_ERROR, "No camera"); 02778 return 0; 02779 } 02780 02781 /* get panorama & ortho, only after camera is set */ 02782 object_camera_mode(&scene->r, camera_override ? camera_override : scene->camera); 02783 02784 /* forbidden combinations */ 02785 if(scene->r.mode & R_PANORAMA) { 02786 if(scene->r.mode & R_ORTHO) { 02787 BKE_report(reports, RPT_ERROR, "No Ortho render possible for Panorama"); 02788 return 0; 02789 } 02790 } 02791 02792 /* layer flag tests */ 02793 if(scene->r.scemode & R_SINGLE_LAYER) { 02794 srl= BLI_findlink(&scene->r.layers, scene->r.actlay); 02795 /* force layer to be enabled */ 02796 srl->layflag &= ~SCE_LAY_DISABLE; 02797 } 02798 02799 for(srl= scene->r.layers.first; srl; srl= srl->next) 02800 if(!(srl->layflag & SCE_LAY_DISABLE)) 02801 break; 02802 if(srl==NULL) { 02803 BKE_report(reports, RPT_ERROR, "All RenderLayers are disabled"); 02804 return 0; 02805 } 02806 02807 /* renderer */ 02808 if(!ELEM(scene->r.renderer, R_INTERN, R_YAFRAY)) { 02809 BKE_report(reports, RPT_ERROR, "Unknown render engine set"); 02810 return 0; 02811 } 02812 02813 return 1; 02814 } 02815 02816 static void validate_render_settings(Render *re) 02817 { 02818 if(re->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE)) { 02819 /* no osa + fullsample won't work... */ 02820 if(re->r.osa==0) 02821 re->r.scemode &= ~R_FULL_SAMPLE; 02822 } else re->r.scemode &= ~R_FULL_SAMPLE; /* clear to be sure */ 02823 } 02824 02825 static void update_physics_cache(Render *re, Scene *scene, int UNUSED(anim_init)) 02826 { 02827 PTCacheBaker baker; 02828 02829 baker.main = re->main; 02830 baker.scene = scene; 02831 baker.pid = NULL; 02832 baker.bake = 0; 02833 baker.render = 1; 02834 baker.anim_init = 1; 02835 baker.quick_step = 1; 02836 baker.break_test = re->test_break; 02837 baker.break_data = re->tbh; 02838 baker.progressbar = NULL; 02839 02840 BKE_ptcache_bake(&baker); 02841 } 02842 /* evaluating scene options for general Blender render */ 02843 static int render_initialize_from_main(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *srl, Object *camera_override, unsigned int lay, int anim, int anim_init) 02844 { 02845 int winx, winy; 02846 rcti disprect; 02847 02848 /* r.xsch and r.ysch has the actual view window size 02849 r.border is the clipping rect */ 02850 02851 /* calculate actual render result and display size */ 02852 winx= (scene->r.size*scene->r.xsch)/100; 02853 winy= (scene->r.size*scene->r.ysch)/100; 02854 02855 /* we always render smaller part, inserting it in larger image is compositor bizz, it uses disprect for it */ 02856 if(scene->r.mode & R_BORDER) { 02857 disprect.xmin= scene->r.border.xmin*winx; 02858 disprect.xmax= scene->r.border.xmax*winx; 02859 02860 disprect.ymin= scene->r.border.ymin*winy; 02861 disprect.ymax= scene->r.border.ymax*winy; 02862 } 02863 else { 02864 disprect.xmin= disprect.ymin= 0; 02865 disprect.xmax= winx; 02866 disprect.ymax= winy; 02867 } 02868 02869 re->main= bmain; 02870 re->scene= scene; 02871 re->camera_override= camera_override; 02872 re->lay= lay; 02873 02874 /* not too nice, but it survives anim-border render */ 02875 if(anim) { 02876 re->disprect= disprect; 02877 return 1; 02878 } 02879 02880 /* check all scenes involved */ 02881 tag_scenes_for_render(re); 02882 02883 /* 02884 * Disabled completely for now, 02885 * can be later set as render profile option 02886 * and default for background render. 02887 */ 02888 if(0) { 02889 /* make sure dynamics are up to date */ 02890 update_physics_cache(re, scene, anim_init); 02891 } 02892 02893 if(srl || scene->r.scemode & R_SINGLE_LAYER) 02894 push_render_result(re); 02895 02896 RE_InitState(re, NULL, &scene->r, srl, winx, winy, &disprect); 02897 if(!re->ok) /* if an error was printed, abort */ 02898 return 0; 02899 02900 /* initstate makes new result, have to send changed tags around */ 02901 ntreeCompositTagRender(re->scene); 02902 02903 validate_render_settings(re); 02904 02905 re->display_init(re->dih, re->result); 02906 re->display_clear(re->dch, re->result); 02907 02908 return 1; 02909 } 02910 02911 void RE_SetReports(Render *re, ReportList *reports) 02912 { 02913 re->reports= reports; 02914 } 02915 02916 /* general Blender frame render call */ 02917 void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *srl, Object *camera_override, unsigned int lay, int frame, const short write_still) 02918 { 02919 /* ugly global still... is to prevent preview events and signal subsurfs etc to make full resol */ 02920 G.rendering= 1; 02921 02922 scene->r.cfra= frame; 02923 02924 if(render_initialize_from_main(re, bmain, scene, srl, camera_override, lay, 0, 0)) { 02925 MEM_reset_peak_memory(); 02926 02927 BLI_exec_cb(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE); 02928 02929 do_render_all_options(re); 02930 02931 if(write_still && !G.afbreek) { 02932 if(BKE_imtype_is_movie(scene->r.imtype)) { 02933 /* operator checks this but incase its called from elsewhere */ 02934 printf("Error: cant write single images with a movie format!\n"); 02935 } 02936 else { 02937 char name[FILE_MAX]; 02938 BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION, FALSE); 02939 02940 /* reports only used for Movie */ 02941 do_write_image_or_movie(re, scene, NULL, name); 02942 } 02943 } 02944 02945 BLI_exec_cb(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */ 02946 } 02947 02948 /* UGLY WARNING */ 02949 G.rendering= 0; 02950 } 02951 02952 static int do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh, const char *name_override) 02953 { 02954 char name[FILE_MAX]; 02955 RenderResult rres; 02956 Object *camera= RE_GetCamera(re); 02957 int ok= 1; 02958 02959 RE_AcquireResultImage(re, &rres); 02960 02961 /* write movie or image */ 02962 if(BKE_imtype_is_movie(scene->r.imtype)) { 02963 int dofree = 0; 02964 /* note; the way it gets 32 bits rects is weak... */ 02965 if(rres.rect32==NULL) { 02966 rres.rect32= MEM_mapallocN(sizeof(int)*rres.rectx*rres.recty, "temp 32 bits rect"); 02967 dofree = 1; 02968 } 02969 RE_ResultGet32(re, (unsigned int *)rres.rect32); 02970 ok= mh->append_movie(&re->r, scene->r.cfra, rres.rect32, rres.rectx, rres.recty, re->reports); 02971 if(dofree) { 02972 MEM_freeN(rres.rect32); 02973 } 02974 printf("Append frame %d", scene->r.cfra); 02975 } 02976 else { 02977 if(name_override) 02978 BLI_strncpy(name, name_override, sizeof(name)); 02979 else 02980 BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION, TRUE); 02981 02982 if(re->r.imtype==R_MULTILAYER) { 02983 if(re->result) { 02984 RE_WriteRenderResult(re->result, name, scene->r.quality); 02985 printf("Saved: %s", name); 02986 } 02987 } 02988 else { 02989 ImBuf *ibuf= IMB_allocImBuf(rres.rectx, rres.recty, scene->r.planes, 0); 02990 02991 /* if not exists, BKE_write_ibuf makes one */ 02992 ibuf->rect= (unsigned int *)rres.rect32; 02993 ibuf->rect_float= rres.rectf; 02994 ibuf->zbuf_float= rres.rectz; 02995 02996 /* float factor for random dither, imbuf takes care of it */ 02997 ibuf->dither= scene->r.dither_intensity; 02998 02999 /* prepare to gamma correct to sRGB color space */ 03000 if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) { 03001 /* sequence editor can generate 8bpc render buffers */ 03002 if (ibuf->rect) { 03003 ibuf->profile = IB_PROFILE_SRGB; 03004 if (ELEM(scene->r.imtype, R_OPENEXR, R_RADHDR)) 03005 IMB_float_from_rect(ibuf); 03006 } else { 03007 ibuf->profile = IB_PROFILE_LINEAR_RGB; 03008 } 03009 } 03010 03011 /* color -> greyscale */ 03012 /* editing directly would alter the render view */ 03013 if(scene->r.planes == 8) { 03014 ImBuf *ibuf_bw= IMB_dupImBuf(ibuf); 03015 IMB_color_to_bw(ibuf_bw); 03016 IMB_freeImBuf(ibuf); 03017 ibuf= ibuf_bw; 03018 } 03019 03020 ok= BKE_write_ibuf_stamp(scene, camera, ibuf, name, scene->r.imtype, scene->r.subimtype, scene->r.quality); 03021 03022 if(ok==0) { 03023 printf("Render error: cannot save %s\n", name); 03024 } 03025 else printf("Saved: %s", name); 03026 03027 /* optional preview images for exr */ 03028 if(ok && scene->r.imtype==R_OPENEXR && (scene->r.subimtype & R_PREVIEW_JPG)) { 03029 if(BLI_testextensie(name, ".exr")) 03030 name[strlen(name)-4]= 0; 03031 BKE_add_image_extension(name, R_JPEG90); 03032 ibuf->depth= 24; 03033 BKE_write_ibuf_stamp(scene, camera, ibuf, name, R_JPEG90, scene->r.subimtype, scene->r.quality); 03034 printf("\nSaved: %s", name); 03035 } 03036 03037 /* imbuf knows which rects are not part of ibuf */ 03038 IMB_freeImBuf(ibuf); 03039 } 03040 } 03041 03042 RE_ReleaseResultImage(re); 03043 03044 BLI_timestr(re->i.lastframetime, name); 03045 printf(" Time: %s\n", name); 03046 fflush(stdout); /* needed for renderd !! (not anymore... (ton)) */ 03047 03048 return ok; 03049 } 03050 03051 /* saves images to disk */ 03052 void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_override, unsigned int lay, int sfra, int efra, int tfra) 03053 { 03054 bMovieHandle *mh= BKE_get_movie_handle(scene->r.imtype); 03055 int cfrao= scene->r.cfra; 03056 int nfra; 03057 03058 /* do not fully call for each frame, it initializes & pops output window */ 03059 if(!render_initialize_from_main(re, bmain, scene, NULL, camera_override, lay, 0, 1)) 03060 return; 03061 03062 /* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */ 03063 /* is also set by caller renderwin.c */ 03064 G.rendering= 1; 03065 03066 if(BKE_imtype_is_movie(scene->r.imtype)) 03067 if(!mh->start_movie(scene, &re->r, re->rectx, re->recty, re->reports)) 03068 G.afbreek= 1; 03069 03070 if (mh->get_next_frame) { 03071 while (!(G.afbreek == 1)) { 03072 int nf = mh->get_next_frame(&re->r, re->reports); 03073 if (nf >= 0 && nf >= scene->r.sfra && nf <= scene->r.efra) { 03074 scene->r.cfra = re->r.cfra = nf; 03075 03076 BLI_exec_cb(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE); 03077 03078 do_render_all_options(re); 03079 03080 if(re->test_break(re->tbh) == 0) { 03081 if(!do_write_image_or_movie(re, scene, mh, NULL)) 03082 G.afbreek= 1; 03083 } 03084 03085 if(G.afbreek == 0) { 03086 BLI_exec_cb(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */ 03087 } 03088 } 03089 else { 03090 if(re->test_break(re->tbh)) 03091 G.afbreek= 1; 03092 } 03093 } 03094 } else { 03095 for(nfra= sfra, scene->r.cfra= sfra; scene->r.cfra<=efra; scene->r.cfra++) { 03096 char name[FILE_MAX]; 03097 03098 /* only border now, todo: camera lens. (ton) */ 03099 render_initialize_from_main(re, bmain, scene, NULL, camera_override, lay, 1, 0); 03100 03101 if(nfra!=scene->r.cfra) { 03102 /* 03103 * Skip this frame, but update for physics and particles system. 03104 * From convertblender.c: 03105 * in localview, lamps are using normal layers, objects only local bits. 03106 */ 03107 unsigned int updatelay; 03108 03109 if(re->lay & 0xFF000000) 03110 updatelay= re->lay & 0xFF000000; 03111 else 03112 updatelay= re->lay; 03113 03114 scene_update_for_newframe(bmain, scene, updatelay); 03115 continue; 03116 } 03117 else 03118 nfra+= tfra; 03119 03120 /* Touch/NoOverwrite options are only valid for image's */ 03121 if(BKE_imtype_is_movie(scene->r.imtype) == 0) { 03122 if(scene->r.mode & (R_NO_OVERWRITE | R_TOUCH)) 03123 BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION, TRUE); 03124 03125 if(scene->r.mode & R_NO_OVERWRITE && BLI_exist(name)) { 03126 printf("skipping existing frame \"%s\"\n", name); 03127 continue; 03128 } 03129 if(scene->r.mode & R_TOUCH && !BLI_exist(name)) { 03130 BLI_make_existing_file(name); /* makes the dir if its not there */ 03131 BLI_touch(name); 03132 } 03133 } 03134 03135 re->r.cfra= scene->r.cfra; /* weak.... */ 03136 03137 /* run callbacs before rendering, before the scene is updated */ 03138 BLI_exec_cb(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE); 03139 03140 03141 do_render_all_options(re); 03142 03143 if(re->test_break(re->tbh) == 0) { 03144 if(!G.afbreek) 03145 if(!do_write_image_or_movie(re, scene, mh, NULL)) 03146 G.afbreek= 1; 03147 } 03148 else 03149 G.afbreek= 1; 03150 03151 if(G.afbreek==1) { 03152 /* remove touched file */ 03153 if(BKE_imtype_is_movie(scene->r.imtype) == 0) { 03154 if (scene->r.mode & R_TOUCH && BLI_exist(name) && BLI_filepathsize(name) == 0) { 03155 BLI_delete(name, 0, 0); 03156 } 03157 } 03158 03159 break; 03160 } 03161 03162 if(G.afbreek==0) { 03163 BLI_exec_cb(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */ 03164 } 03165 } 03166 } 03167 03168 /* end movie */ 03169 if(BKE_imtype_is_movie(scene->r.imtype)) 03170 mh->end_movie(); 03171 03172 scene->r.cfra= cfrao; 03173 03174 /* UGLY WARNING */ 03175 G.rendering= 0; 03176 } 03177 03178 void RE_PreviewRender(Render *re, Main *bmain, Scene *sce) 03179 { 03180 Object *camera; 03181 int winx, winy; 03182 03183 winx= (sce->r.size*sce->r.xsch)/100; 03184 winy= (sce->r.size*sce->r.ysch)/100; 03185 03186 RE_InitState(re, NULL, &sce->r, NULL, winx, winy, NULL); 03187 03188 re->main = bmain; 03189 re->scene = sce; 03190 re->lay = sce->lay; 03191 03192 camera = RE_GetCamera(re); 03193 RE_SetCamera(re, camera); 03194 03195 do_render_3d(re); 03196 } 03197 03198 /* note; repeated win/disprect calc... solve that nicer, also in compo */ 03199 03200 /* only the temp file! */ 03201 void RE_ReadRenderResult(Scene *scene, Scene *scenode) 03202 { 03203 Render *re; 03204 int winx, winy; 03205 rcti disprect; 03206 03207 /* calculate actual render result and display size */ 03208 winx= (scene->r.size*scene->r.xsch)/100; 03209 winy= (scene->r.size*scene->r.ysch)/100; 03210 03211 /* only in movie case we render smaller part */ 03212 if(scene->r.mode & R_BORDER) { 03213 disprect.xmin= scene->r.border.xmin*winx; 03214 disprect.xmax= scene->r.border.xmax*winx; 03215 03216 disprect.ymin= scene->r.border.ymin*winy; 03217 disprect.ymax= scene->r.border.ymax*winy; 03218 } 03219 else { 03220 disprect.xmin= disprect.ymin= 0; 03221 disprect.xmax= winx; 03222 disprect.ymax= winy; 03223 } 03224 03225 if(scenode) 03226 scene= scenode; 03227 03228 /* get render: it can be called from UI with draw callbacks */ 03229 re= RE_GetRender(scene->id.name); 03230 if(re==NULL) 03231 re= RE_NewRender(scene->id.name); 03232 RE_InitState(re, NULL, &scene->r, NULL, winx, winy, &disprect); 03233 re->scene= scene; 03234 03235 read_render_result(re, 0); 03236 } 03237 03238 void RE_set_max_threads(int threads) 03239 { 03240 if (threads==0) { 03241 RenderGlobal.threads = BLI_system_thread_count(); 03242 } else if(threads>=1 && threads<=BLENDER_MAX_THREADS) { 03243 RenderGlobal.threads= threads; 03244 } else { 03245 printf("Error, threads has to be in range 0-%d\n", BLENDER_MAX_THREADS); 03246 } 03247 } 03248 03249 void RE_init_threadcount(Render *re) 03250 { 03251 if(RenderGlobal.threads >= 1) { /* only set as an arg in background mode */ 03252 re->r.threads= MIN2(RenderGlobal.threads, BLENDER_MAX_THREADS); 03253 } else if ((re->r.mode & R_FIXED_THREADS)==0 || RenderGlobal.threads == 0) { /* Automatic threads */ 03254 re->r.threads = BLI_system_thread_count(); 03255 } 03256 } 03257 03258 /************************** External Engines ***************************/ 03259 03260 RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h) 03261 { 03262 Render *re= engine->re; 03263 RenderResult *result; 03264 rcti disprect; 03265 03266 /* ensure the coordinates are within the right limits */ 03267 CLAMP(x, 0, re->result->rectx); 03268 CLAMP(y, 0, re->result->recty); 03269 CLAMP(w, 0, re->result->rectx); 03270 CLAMP(h, 0, re->result->recty); 03271 03272 if(x + w > re->result->rectx) 03273 w= re->result->rectx - x; 03274 if(y + h > re->result->recty) 03275 h= re->result->recty - y; 03276 03277 /* allocate a render result */ 03278 disprect.xmin= x; 03279 disprect.xmax= x+w; 03280 disprect.ymin= y; 03281 disprect.ymax= y+h; 03282 03283 if(0) { // XXX (re->r.scemode & R_FULL_SAMPLE)) { 03284 result= new_full_sample_buffers(re, &engine->fullresult, &disprect, 0); 03285 } 03286 else { 03287 result= new_render_result(re, &disprect, 0, RR_USEMEM); 03288 BLI_addtail(&engine->fullresult, result); 03289 } 03290 03291 return result; 03292 } 03293 03294 void RE_engine_update_result(RenderEngine *engine, RenderResult *result) 03295 { 03296 Render *re= engine->re; 03297 03298 if(result && render_display_draw_enabled(re)) { 03299 result->renlay= result->layers.first; // weak 03300 re->display_draw(re->ddh, result, NULL); 03301 } 03302 } 03303 03304 void RE_engine_end_result(RenderEngine *engine, RenderResult *result) 03305 { 03306 Render *re= engine->re; 03307 03308 if(!result) 03309 return; 03310 03311 /* merge */ 03312 if(re->result->exrhandle) { 03313 RenderResult *rr, *rrpart; 03314 03315 // XXX crashes, exr expects very particular part sizes 03316 for(rr= re->result, rrpart= result; rr && rrpart; rr= rr->next, rrpart= rrpart->next) 03317 save_render_result_tile(rr, rrpart); 03318 } 03319 else if(render_display_draw_enabled(re)) { 03320 /* on break, don't merge in result for preview renders, looks nicer */ 03321 if(re->test_break(re->tbh) && (re->r.scemode & R_PREVIEWBUTS)); 03322 else merge_render_result(re->result, result); 03323 } 03324 03325 /* draw */ 03326 if(!re->test_break(re->tbh) && render_display_draw_enabled(re)) { 03327 result->renlay= result->layers.first; // weak 03328 re->display_draw(re->ddh, result, NULL); 03329 } 03330 03331 /* free */ 03332 free_render_result(&engine->fullresult, result); 03333 } 03334 03335 int RE_engine_test_break(RenderEngine *engine) 03336 { 03337 Render *re= engine->re; 03338 03339 return re->test_break(re->tbh); 03340 } 03341 03342 void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info) 03343 { 03344 Render *re= engine->re; 03345 03346 re->i.statstr= stats; 03347 re->i.infostr= info; 03348 re->stats_draw(re->sdh, &re->i); 03349 re->i.infostr= NULL; 03350 re->i.statstr= NULL; 03351 } 03352 03353 void RE_engine_report(RenderEngine *engine, int type, const char *msg) 03354 { 03355 BKE_report(engine->re->reports, type, msg); 03356 } 03357 03358 /* loads in image into a result, size must match 03359 * x/y offsets are only used on a partial copy when dimensions dont match */ 03360 void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char *filename, int x, int y) 03361 { 03362 ImBuf *ibuf = IMB_loadiffname(filename, IB_rect); 03363 03364 if(ibuf && (ibuf->rect || ibuf->rect_float)) { 03365 if (ibuf->x == layer->rectx && ibuf->y == layer->recty) { 03366 if(ibuf->rect_float==NULL) 03367 IMB_float_from_rect(ibuf); 03368 03369 memcpy(layer->rectf, ibuf->rect_float, sizeof(float)*4*layer->rectx*layer->recty); 03370 } else { 03371 if ((ibuf->x - x >= layer->rectx) && (ibuf->y - y >= layer->recty)) { 03372 ImBuf *ibuf_clip; 03373 03374 if(ibuf->rect_float==NULL) 03375 IMB_float_from_rect(ibuf); 03376 03377 ibuf_clip = IMB_allocImBuf(layer->rectx, layer->recty, 32, IB_rectfloat); 03378 if(ibuf_clip) { 03379 IMB_rectcpy(ibuf_clip, ibuf, 0,0, x,y, layer->rectx, layer->recty); 03380 03381 memcpy(layer->rectf, ibuf_clip->rect_float, sizeof(float)*4*layer->rectx*layer->recty); 03382 IMB_freeImBuf(ibuf_clip); 03383 } 03384 else { 03385 BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to allocate clip buffer '%s'\n", filename); 03386 } 03387 } 03388 else { 03389 BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: incorrect dimensions for partial copy '%s'\n", filename); 03390 } 03391 } 03392 03393 IMB_freeImBuf(ibuf); 03394 } 03395 else { 03396 BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'\n", filename); 03397 } 03398 } 03399 03400 void RE_result_load_from_file(RenderResult *result, ReportList *reports, const char *filename) 03401 { 03402 if(!read_render_result_from_file(filename, result)) { 03403 BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'\n", filename); 03404 return; 03405 } 03406 } 03407 03408 static int external_render_3d(Render *re, int do_all) 03409 { 03410 RenderEngineType *type= BLI_findstring(&R_engines, re->r.engine, offsetof(RenderEngineType, idname)); 03411 RenderEngine engine; 03412 03413 if(!(type && type->render)) 03414 return 0; 03415 if((re->r.scemode & R_PREVIEWBUTS) && !(type->flag & RE_DO_PREVIEW)) 03416 return 0; 03417 if(do_all && !(type->flag & RE_DO_ALL)) 03418 return 0; 03419 if(!do_all && (type->flag & RE_DO_ALL)) 03420 return 0; 03421 03422 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 03423 if(re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) { 03424 RE_FreeRenderResult(re->result); 03425 03426 if(0) // XXX re->r.scemode & R_FULL_SAMPLE) 03427 re->result= new_full_sample_buffers_exr(re); 03428 else 03429 re->result= new_render_result(re, &re->disprect, 0, 0); // XXX re->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE)); 03430 } 03431 BLI_rw_mutex_unlock(&re->resultmutex); 03432 03433 if(re->result==NULL) 03434 return 1; 03435 03436 /* external */ 03437 memset(&engine, 0, sizeof(engine)); 03438 engine.type= type; 03439 engine.re= re; 03440 03441 type->render(&engine, re->scene); 03442 03443 free_render_result(&engine.fullresult, engine.fullresult.first); 03444 03445 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 03446 if(re->result->exrhandle) { 03447 RenderResult *rr; 03448 03449 save_empty_result_tiles(re); 03450 03451 for(rr= re->result; rr; rr= rr->next) { 03452 IMB_exr_close(rr->exrhandle); 03453 rr->exrhandle= NULL; 03454 } 03455 03456 free_render_result(&re->fullresult, re->result); 03457 re->result= NULL; 03458 03459 read_render_result(re, 0); 03460 } 03461 BLI_rw_mutex_unlock(&re->resultmutex); 03462 03463 return 1; 03464 } 03465