|
Blender
V2.59
|
00001 /* 00002 * $Id: rendercore.c 38964 2011-08-03 05:32:07Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * Contributors: Hos, Robert Wenzlaff. 00024 * Contributors: 2004/2005/2006 Blender Foundation, full recode 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00034 /* system includes */ 00035 #include <stdio.h> 00036 #include <math.h> 00037 #include <float.h> 00038 #include <string.h> 00039 #include <assert.h> 00040 00041 /* External modules: */ 00042 #include "MEM_guardedalloc.h" 00043 00044 #include "BLI_math.h" 00045 #include "BLI_blenlib.h" 00046 #include "BLI_jitter.h" 00047 #include "BLI_rand.h" 00048 #include "BLI_threads.h" 00049 #include "BLI_utildefines.h" 00050 00051 00052 00053 #include "DNA_image_types.h" 00054 #include "DNA_lamp_types.h" 00055 #include "DNA_material_types.h" 00056 #include "DNA_meshdata_types.h" 00057 #include "DNA_group_types.h" 00058 00059 #include "BKE_global.h" 00060 #include "BKE_image.h" 00061 #include "BKE_main.h" 00062 #include "BKE_node.h" 00063 #include "BKE_texture.h" 00064 00065 #include "IMB_imbuf_types.h" 00066 #include "IMB_imbuf.h" 00067 00068 /* local include */ 00069 #include "rayintersection.h" 00070 #include "rayobject.h" 00071 #include "renderpipeline.h" 00072 #include "render_types.h" 00073 #include "renderdatabase.h" 00074 #include "occlusion.h" 00075 #include "pixelblending.h" 00076 #include "pixelshading.h" 00077 #include "shadbuf.h" 00078 #include "shading.h" 00079 #include "sss.h" 00080 #include "zbuf.h" 00081 00082 #include "PIL_time.h" 00083 00084 /* own include */ 00085 #include "rendercore.h" 00086 00087 00088 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00089 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ 00090 /* only to be used here in this file, it's for speed */ 00091 extern struct Render R; 00092 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00093 00094 /* x and y are current pixels in rect to be rendered */ 00095 /* do not normalize! */ 00096 void calc_view_vector(float *view, float x, float y) 00097 { 00098 00099 view[2]= -ABS(R.clipsta); 00100 00101 if(R.r.mode & R_ORTHO) { 00102 view[0]= view[1]= 0.0f; 00103 } 00104 else { 00105 00106 if(R.r.mode & R_PANORAMA) { 00107 x-= R.panodxp; 00108 } 00109 00110 /* move x and y to real viewplane coords */ 00111 x= (x/(float)R.winx); 00112 view[0]= R.viewplane.xmin + x*(R.viewplane.xmax - R.viewplane.xmin); 00113 00114 y= (y/(float)R.winy); 00115 view[1]= R.viewplane.ymin + y*(R.viewplane.ymax - R.viewplane.ymin); 00116 00117 // if(R.flag & R_SEC_FIELD) { 00118 // if(R.r.mode & R_ODDFIELD) view[1]= (y+R.ystart)*R.ycor; 00119 // else view[1]= (y+R.ystart+1.0)*R.ycor; 00120 // } 00121 // else view[1]= (y+R.ystart+R.bluroffsy+0.5)*R.ycor; 00122 00123 if(R.r.mode & R_PANORAMA) { 00124 float u= view[0] + R.panodxv; float v= view[2]; 00125 view[0]= R.panoco*u + R.panosi*v; 00126 view[2]= -R.panosi*u + R.panoco*v; 00127 } 00128 } 00129 } 00130 00131 void calc_renderco_ortho(float *co, float x, float y, int z) 00132 { 00133 /* x and y 3d coordinate can be derived from pixel coord and winmat */ 00134 float fx= 2.0f/(R.winx*R.winmat[0][0]); 00135 float fy= 2.0f/(R.winy*R.winmat[1][1]); 00136 float zco; 00137 00138 co[0]= (x - 0.5f*R.winx)*fx - R.winmat[3][0]/R.winmat[0][0]; 00139 co[1]= (y - 0.5f*R.winy)*fy - R.winmat[3][1]/R.winmat[1][1]; 00140 00141 zco= ((float)z)/2147483647.0f; 00142 co[2]= R.winmat[3][2]/( R.winmat[2][3]*zco - R.winmat[2][2] ); 00143 } 00144 00145 void calc_renderco_zbuf(float *co, float *view, int z) 00146 { 00147 float fac, zco; 00148 00149 /* inverse of zbuf calc: zbuf = MAXZ*hoco_z/hoco_w */ 00150 zco= ((float)z)/2147483647.0f; 00151 co[2]= R.winmat[3][2]/( R.winmat[2][3]*zco - R.winmat[2][2] ); 00152 00153 fac= co[2]/view[2]; 00154 co[0]= fac*view[0]; 00155 co[1]= fac*view[1]; 00156 } 00157 00158 /* also used in zbuf.c and shadbuf.c */ 00159 int count_mask(unsigned short mask) 00160 { 00161 if(R.samples) 00162 return (R.samples->cmask[mask & 255]+R.samples->cmask[mask>>8]); 00163 return 0; 00164 } 00165 00166 static int calchalo_z(HaloRen *har, int zz) 00167 { 00168 00169 if(har->type & HA_ONLYSKY) { 00170 if(zz < 0x7FFFFFF0) zz= - 0x7FFFFF; /* edge render messes zvalues */ 00171 } 00172 else { 00173 zz= (zz>>8); 00174 } 00175 return zz; 00176 } 00177 00178 00179 00180 static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, int od, float dist, float xn, float yn, PixStr *ps) 00181 { 00182 float col[4], accol[4], fac; 00183 int amount, amountm, zz, flarec, sample, fullsample, mask=0; 00184 00185 fullsample= (totsample > 1); 00186 amount= 0; 00187 accol[0]=accol[1]=accol[2]=accol[3]= 0.0f; 00188 flarec= har->flarec; 00189 00190 while(ps) { 00191 amountm= count_mask(ps->mask); 00192 amount+= amountm; 00193 00194 zz= calchalo_z(har, ps->z); 00195 if((zz> har->zs) || (har->mat && (har->mat->mode & MA_HALO_SOFT))) { 00196 if(shadeHaloFloat(har, col, zz, dist, xn, yn, flarec)) { 00197 flarec= 0; 00198 00199 if(fullsample) { 00200 for(sample=0; sample<totsample; sample++) 00201 if(ps->mask & (1 << sample)) 00202 addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add); 00203 } 00204 else { 00205 fac= ((float)amountm)/(float)R.osa; 00206 accol[0]+= fac*col[0]; 00207 accol[1]+= fac*col[1]; 00208 accol[2]+= fac*col[2]; 00209 accol[3]+= fac*col[3]; 00210 } 00211 } 00212 } 00213 00214 mask |= ps->mask; 00215 ps= ps->next; 00216 } 00217 00218 /* now do the sky sub-pixels */ 00219 amount= R.osa-amount; 00220 if(amount) { 00221 if(shadeHaloFloat(har, col, 0x7FFFFF, dist, xn, yn, flarec)) { 00222 if(!fullsample) { 00223 fac= ((float)amount)/(float)R.osa; 00224 accol[0]+= fac*col[0]; 00225 accol[1]+= fac*col[1]; 00226 accol[2]+= fac*col[2]; 00227 accol[3]+= fac*col[3]; 00228 } 00229 } 00230 } 00231 00232 if(fullsample) { 00233 for(sample=0; sample<totsample; sample++) 00234 if(!(mask & (1 << sample))) 00235 addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add); 00236 } 00237 else { 00238 col[0]= accol[0]; 00239 col[1]= accol[1]; 00240 col[2]= accol[2]; 00241 col[3]= accol[3]; 00242 00243 for(sample=0; sample<totsample; sample++) 00244 addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add); 00245 } 00246 } 00247 00248 static void halo_tile(RenderPart *pa, RenderLayer *rl) 00249 { 00250 RenderLayer *rlpp[RE_MAX_OSA]; 00251 HaloRen *har; 00252 rcti disprect= pa->disprect, testrect= pa->disprect; 00253 float dist, xsq, ysq, xn, yn; 00254 float col[4]; 00255 intptr_t *rd= NULL; 00256 int a, *rz, zz, y, sample, totsample, od; 00257 short minx, maxx, miny, maxy, x; 00258 unsigned int lay= rl->lay; 00259 00260 /* we don't render halos in the cropped area, gives errors in flare counter */ 00261 if(pa->crop) { 00262 testrect.xmin+= pa->crop; 00263 testrect.xmax-= pa->crop; 00264 testrect.ymin+= pa->crop; 00265 testrect.ymax-= pa->crop; 00266 } 00267 00268 totsample= get_sample_layers(pa, rl, rlpp); 00269 00270 for(a=0; a<R.tothalo; a++) { 00271 har= R.sortedhalos[a]; 00272 00273 /* layer test, clip halo with y */ 00274 if((har->lay & lay)==0); 00275 else if(testrect.ymin > har->maxy); 00276 else if(testrect.ymax < har->miny); 00277 else { 00278 00279 minx= floor(har->xs-har->rad); 00280 maxx= ceil(har->xs+har->rad); 00281 00282 if(testrect.xmin > maxx); 00283 else if(testrect.xmax < minx); 00284 else { 00285 00286 minx= MAX2(minx, testrect.xmin); 00287 maxx= MIN2(maxx, testrect.xmax); 00288 00289 miny= MAX2(har->miny, testrect.ymin); 00290 maxy= MIN2(har->maxy, testrect.ymax); 00291 00292 for(y=miny; y<maxy; y++) { 00293 int rectofs= (y-disprect.ymin)*pa->rectx + (minx - disprect.xmin); 00294 rz= pa->rectz + rectofs; 00295 od= rectofs; 00296 00297 if(pa->rectdaps) 00298 rd= pa->rectdaps + rectofs; 00299 00300 yn= (y-har->ys)*R.ycor; 00301 ysq= yn*yn; 00302 00303 for(x=minx; x<maxx; x++, rz++, od++) { 00304 xn= x- har->xs; 00305 xsq= xn*xn; 00306 dist= xsq+ysq; 00307 if(dist<har->radsq) { 00308 if(rd && *rd) { 00309 halo_pixelstruct(har, rlpp, totsample, od, dist, xn, yn, (PixStr *)*rd); 00310 } 00311 else { 00312 zz= calchalo_z(har, *rz); 00313 if((zz> har->zs) || (har->mat && (har->mat->mode & MA_HALO_SOFT))) { 00314 if(shadeHaloFloat(har, col, zz, dist, xn, yn, har->flarec)) { 00315 for(sample=0; sample<totsample; sample++) 00316 addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add); 00317 } 00318 } 00319 } 00320 } 00321 if(rd) rd++; 00322 } 00323 } 00324 } 00325 } 00326 if(R.test_break(R.tbh) ) break; 00327 } 00328 } 00329 00330 static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) 00331 { 00332 RenderLayer *rlpp[RE_MAX_OSA]; 00333 ShadeInput shi; 00334 float *pass; 00335 float fac, col[4]; 00336 intptr_t *rd= pa->rectdaps; 00337 int *rz= pa->rectz; 00338 int x, y, sample, totsample, fullsample, od; 00339 00340 totsample= get_sample_layers(pa, rl, rlpp); 00341 fullsample= (totsample > 1); 00342 00343 shade_input_initialize(&shi, pa, rl, 0); /* this zero's ShadeInput for us */ 00344 00345 for(od=0, y=pa->disprect.ymin; y<pa->disprect.ymax; y++) { 00346 for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, rz++, od++) { 00347 00348 calc_view_vector(shi.view, x, y); 00349 00350 if(rd && *rd) { 00351 PixStr *ps= (PixStr *)*rd; 00352 int count, totsamp= 0, mask= 0; 00353 00354 while(ps) { 00355 if(R.r.mode & R_ORTHO) 00356 calc_renderco_ortho(shi.co, (float)x, (float)y, ps->z); 00357 else 00358 calc_renderco_zbuf(shi.co, shi.view, ps->z); 00359 00360 totsamp+= count= count_mask(ps->mask); 00361 mask |= ps->mask; 00362 00363 col[0]= col[1]= col[2]= col[3]= 0.0f; 00364 renderspothalo(&shi, col, 1.0f); 00365 00366 if(fullsample) { 00367 for(sample=0; sample<totsample; sample++) { 00368 if(ps->mask & (1 << sample)) { 00369 pass= rlpp[sample]->rectf + od*4; 00370 pass[0]+= col[0]; 00371 pass[1]+= col[1]; 00372 pass[2]+= col[2]; 00373 pass[3]+= col[3]; 00374 if(pass[3]>1.0f) pass[3]= 1.0f; 00375 } 00376 } 00377 } 00378 else { 00379 fac= ((float)count)/(float)R.osa; 00380 pass= rl->rectf + od*4; 00381 pass[0]+= fac*col[0]; 00382 pass[1]+= fac*col[1]; 00383 pass[2]+= fac*col[2]; 00384 pass[3]+= fac*col[3]; 00385 if(pass[3]>1.0f) pass[3]= 1.0f; 00386 } 00387 00388 ps= ps->next; 00389 } 00390 00391 if(totsamp<R.osa) { 00392 shi.co[2]= 0.0f; 00393 00394 col[0]= col[1]= col[2]= col[3]= 0.0f; 00395 renderspothalo(&shi, col, 1.0f); 00396 00397 if(fullsample) { 00398 for(sample=0; sample<totsample; sample++) { 00399 if(!(mask & (1 << sample))) { 00400 pass= rlpp[sample]->rectf + od*4; 00401 pass[0]+= col[0]; 00402 pass[1]+= col[1]; 00403 pass[2]+= col[2]; 00404 pass[3]+= col[3]; 00405 if(pass[3]>1.0f) pass[3]= 1.0f; 00406 } 00407 } 00408 } 00409 else { 00410 fac= ((float)R.osa-totsamp)/(float)R.osa; 00411 pass= rl->rectf + od*4; 00412 pass[0]+= fac*col[0]; 00413 pass[1]+= fac*col[1]; 00414 pass[2]+= fac*col[2]; 00415 pass[3]+= fac*col[3]; 00416 if(pass[3]>1.0f) pass[3]= 1.0f; 00417 } 00418 } 00419 } 00420 else { 00421 if(R.r.mode & R_ORTHO) 00422 calc_renderco_ortho(shi.co, (float)x, (float)y, *rz); 00423 else 00424 calc_renderco_zbuf(shi.co, shi.view, *rz); 00425 00426 col[0]= col[1]= col[2]= col[3]= 0.0f; 00427 renderspothalo(&shi, col, 1.0f); 00428 00429 for(sample=0; sample<totsample; sample++) { 00430 pass= rlpp[sample]->rectf + od*4; 00431 pass[0]+= col[0]; 00432 pass[1]+= col[1]; 00433 pass[2]+= col[2]; 00434 pass[3]+= col[3]; 00435 if(pass[3]>1.0f) pass[3]= 1.0f; 00436 } 00437 } 00438 00439 if(rd) rd++; 00440 } 00441 if(y&1) 00442 if(R.test_break(R.tbh)) break; 00443 } 00444 } 00445 00446 00447 /* ********************* MAINLOOPS ******************** */ 00448 00449 /* osa version */ 00450 static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, ShadeInput *shi, ShadeResult *shr) 00451 { 00452 RenderPass *rpass; 00453 00454 /* combined rgb */ 00455 add_filt_fmask(curmask, shr->combined, rl->rectf + 4*offset, rectx); 00456 00457 for(rpass= rl->passes.first; rpass; rpass= rpass->next) { 00458 float *fp, *col= NULL; 00459 int pixsize= 3; 00460 00461 switch(rpass->passtype) { 00462 case SCE_PASS_Z: 00463 fp= rpass->rect + offset; 00464 *fp= shr->z; 00465 break; 00466 case SCE_PASS_RGBA: 00467 col= shr->col; 00468 pixsize= 4; 00469 break; 00470 case SCE_PASS_EMIT: 00471 col= shr->emit; 00472 break; 00473 case SCE_PASS_DIFFUSE: 00474 col= shr->diff; 00475 break; 00476 case SCE_PASS_SPEC: 00477 col= shr->spec; 00478 break; 00479 case SCE_PASS_SHADOW: 00480 col= shr->shad; 00481 break; 00482 case SCE_PASS_AO: 00483 col= shr->ao; 00484 break; 00485 case SCE_PASS_ENVIRONMENT: 00486 col= shr->env; 00487 break; 00488 case SCE_PASS_INDIRECT: 00489 col= shr->indirect; 00490 break; 00491 case SCE_PASS_REFLECT: 00492 col= shr->refl; 00493 break; 00494 case SCE_PASS_REFRACT: 00495 col= shr->refr; 00496 break; 00497 case SCE_PASS_NORMAL: 00498 col= shr->nor; 00499 break; 00500 case SCE_PASS_UV: 00501 /* box filter only, gauss will screwup UV too much */ 00502 if(shi->totuv) { 00503 float mult= (float)count_mask(curmask)/(float)R.osa; 00504 fp= rpass->rect + 3*offset; 00505 fp[0]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[0]); 00506 fp[1]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[1]); 00507 fp[2]+= mult; 00508 } 00509 break; 00510 case SCE_PASS_INDEXOB: 00511 /* no filter */ 00512 if(shi->vlr) { 00513 fp= rpass->rect + offset; 00514 if(*fp==0.0f) 00515 *fp= (float)shi->obr->ob->index; 00516 } 00517 break; 00518 case SCE_PASS_INDEXMA: 00519 /* no filter */ 00520 if(shi->vlr) { 00521 fp= rpass->rect + offset; 00522 if(*fp==0.0f) 00523 *fp= (float)shi->mat->index; 00524 } 00525 break; 00526 case SCE_PASS_MIST: 00527 /* */ 00528 col= &shr->mist; 00529 pixsize= 1; 00530 break; 00531 00532 case SCE_PASS_VECTOR: 00533 { 00534 /* add minimum speed in pixel, no filter */ 00535 fp= rpass->rect + 4*offset; 00536 if( (ABS(shr->winspeed[0]) + ABS(shr->winspeed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) { 00537 fp[0]= shr->winspeed[0]; 00538 fp[1]= shr->winspeed[1]; 00539 } 00540 if( (ABS(shr->winspeed[2]) + ABS(shr->winspeed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) { 00541 fp[2]= shr->winspeed[2]; 00542 fp[3]= shr->winspeed[3]; 00543 } 00544 } 00545 break; 00546 00547 case SCE_PASS_RAYHITS: 00548 /* */ 00549 col= shr->rayhits; 00550 pixsize= 4; 00551 break; 00552 } 00553 if(col) { 00554 fp= rpass->rect + pixsize*offset; 00555 add_filt_fmask_pixsize(curmask, col, fp, rectx, pixsize); 00556 } 00557 } 00558 } 00559 00560 /* non-osa version */ 00561 static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult *shr) 00562 { 00563 RenderPass *rpass; 00564 float *fp; 00565 00566 fp= rl->rectf + 4*offset; 00567 QUATCOPY(fp, shr->combined); 00568 00569 for(rpass= rl->passes.first; rpass; rpass= rpass->next) { 00570 float *col= NULL, uvcol[3]; 00571 int a, pixsize= 3; 00572 00573 switch(rpass->passtype) { 00574 case SCE_PASS_Z: 00575 fp= rpass->rect + offset; 00576 *fp= shr->z; 00577 break; 00578 case SCE_PASS_RGBA: 00579 col= shr->col; 00580 pixsize= 4; 00581 break; 00582 case SCE_PASS_EMIT: 00583 col= shr->emit; 00584 break; 00585 case SCE_PASS_DIFFUSE: 00586 col= shr->diff; 00587 break; 00588 case SCE_PASS_SPEC: 00589 col= shr->spec; 00590 break; 00591 case SCE_PASS_SHADOW: 00592 col= shr->shad; 00593 break; 00594 case SCE_PASS_AO: 00595 col= shr->ao; 00596 break; 00597 case SCE_PASS_ENVIRONMENT: 00598 col= shr->env; 00599 break; 00600 case SCE_PASS_INDIRECT: 00601 col= shr->indirect; 00602 break; 00603 case SCE_PASS_REFLECT: 00604 col= shr->refl; 00605 break; 00606 case SCE_PASS_REFRACT: 00607 col= shr->refr; 00608 break; 00609 case SCE_PASS_NORMAL: 00610 col= shr->nor; 00611 break; 00612 case SCE_PASS_UV: 00613 if(shi->totuv) { 00614 uvcol[0]= 0.5f + 0.5f*shi->uv[shi->actuv].uv[0]; 00615 uvcol[1]= 0.5f + 0.5f*shi->uv[shi->actuv].uv[1]; 00616 uvcol[2]= 1.0f; 00617 col= uvcol; 00618 } 00619 break; 00620 case SCE_PASS_VECTOR: 00621 col= shr->winspeed; 00622 pixsize= 4; 00623 break; 00624 case SCE_PASS_INDEXOB: 00625 if(shi->vlr) { 00626 fp= rpass->rect + offset; 00627 *fp= (float)shi->obr->ob->index; 00628 } 00629 break; 00630 case SCE_PASS_INDEXMA: 00631 if(shi->vlr) { 00632 fp= rpass->rect + offset; 00633 *fp= (float)shi->mat->index; 00634 } 00635 break; 00636 case SCE_PASS_MIST: 00637 fp= rpass->rect + offset; 00638 *fp= shr->mist; 00639 break; 00640 case SCE_PASS_RAYHITS: 00641 col= shr->rayhits; 00642 pixsize= 4; 00643 break; 00644 } 00645 if(col) { 00646 fp= rpass->rect + pixsize*offset; 00647 for(a=0; a<pixsize; a++) 00648 fp[a]= col[a]; 00649 } 00650 } 00651 } 00652 00653 int get_sample_layers(RenderPart *pa, RenderLayer *rl, RenderLayer **rlpp) 00654 { 00655 00656 if(pa->fullresult.first) { 00657 int sample, nr= BLI_findindex(&pa->result->layers, rl); 00658 00659 for(sample=0; sample<R.osa; sample++) { 00660 RenderResult *rr= BLI_findlink(&pa->fullresult, sample); 00661 00662 rlpp[sample]= BLI_findlink(&rr->layers, nr); 00663 } 00664 return R.osa; 00665 } 00666 else { 00667 rlpp[0]= rl; 00668 return 1; 00669 } 00670 } 00671 00672 00673 /* only do sky, is default in the solid layer (shade_tile) btw */ 00674 static void sky_tile(RenderPart *pa, RenderLayer *rl) 00675 { 00676 RenderLayer *rlpp[RE_MAX_OSA]; 00677 int x, y, od=0, totsample; 00678 00679 if(R.r.alphamode!=R_ADDSKY) 00680 return; 00681 00682 totsample= get_sample_layers(pa, rl, rlpp); 00683 00684 for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++) { 00685 for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, od+=4) { 00686 float col[4]; 00687 int sample, done= 0; 00688 00689 for(sample= 0; sample<totsample; sample++) { 00690 float *pass= rlpp[sample]->rectf + od; 00691 00692 if(pass[3]<1.0f) { 00693 00694 if(done==0) { 00695 shadeSkyPixel(col, x, y, pa->thread); 00696 done= 1; 00697 } 00698 00699 if(pass[3]==0.0f) { 00700 QUATCOPY(pass, col); 00701 } 00702 else { 00703 addAlphaUnderFloat(pass, col); 00704 } 00705 } 00706 } 00707 } 00708 00709 if(y&1) 00710 if(R.test_break(R.tbh)) break; 00711 } 00712 } 00713 00714 static void atm_tile(RenderPart *pa, RenderLayer *rl) 00715 { 00716 RenderPass *zpass; 00717 GroupObject *go; 00718 LampRen *lar; 00719 RenderLayer *rlpp[RE_MAX_OSA]; 00720 int totsample; 00721 int x, y, od= 0; 00722 00723 totsample= get_sample_layers(pa, rl, rlpp); 00724 00725 /* check that z pass is enabled */ 00726 if(pa->rectz==NULL) return; 00727 for(zpass= rl->passes.first; zpass; zpass= zpass->next) 00728 if(zpass->passtype==SCE_PASS_Z) 00729 break; 00730 00731 if(zpass==NULL) return; 00732 00733 /* check for at least one sun lamp that its atmosphere flag is enabled */ 00734 for(go=R.lights.first; go; go= go->next) { 00735 lar= go->lampren; 00736 if(lar->type==LA_SUN && lar->sunsky && (lar->sunsky->effect_type & LA_SUN_EFFECT_AP)) 00737 break; 00738 } 00739 /* do nothign and return if there is no sun lamp */ 00740 if(go==NULL) 00741 return; 00742 00743 /* for each x,y and each sample, and each sun lamp*/ 00744 for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++) { 00745 for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, od++) { 00746 int sample; 00747 00748 for(sample=0; sample<totsample; sample++) { 00749 float *zrect= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_Z) + od; 00750 float *rgbrect = rlpp[sample]->rectf + 4*od; 00751 float rgb[3] = {0}; 00752 int done= 0; 00753 00754 for(go=R.lights.first; go; go= go->next) { 00755 00756 00757 lar= go->lampren; 00758 if(lar->type==LA_SUN && lar->sunsky) { 00759 00760 /* if it's sky continue and don't apply atmosphere effect on it */ 00761 if(*zrect >= 9.9e10 || rgbrect[3]==0.0f) { 00762 continue; 00763 } 00764 00765 if((lar->sunsky->effect_type & LA_SUN_EFFECT_AP)) { 00766 float tmp_rgb[3]; 00767 00768 /* skip if worldspace lamp vector is below horizon */ 00769 if(go->ob->obmat[2][2] < 0.f) { 00770 continue; 00771 } 00772 00773 VECCOPY(tmp_rgb, rgbrect); 00774 if(rgbrect[3]!=1.0f) { /* de-premul */ 00775 float div= 1.0f/rgbrect[3]; 00776 VECMUL(tmp_rgb, div); 00777 } 00778 shadeAtmPixel(lar->sunsky, tmp_rgb, x, y, *zrect); 00779 if(rgbrect[3]!=1.0f) { /* premul */ 00780 VECMUL(tmp_rgb, rgbrect[3]); 00781 } 00782 00783 if(done==0) { 00784 VECCOPY(rgb, tmp_rgb); 00785 done = 1; 00786 } 00787 else{ 00788 rgb[0] = 0.5f*rgb[0] + 0.5f*tmp_rgb[0]; 00789 rgb[1] = 0.5f*rgb[1] + 0.5f*tmp_rgb[1]; 00790 rgb[2] = 0.5f*rgb[2] + 0.5f*tmp_rgb[2]; 00791 } 00792 } 00793 } 00794 } 00795 00796 /* if at least for one sun lamp aerial perspective was applied*/ 00797 if(done) { 00798 VECCOPY(rgbrect, rgb); 00799 } 00800 } 00801 } 00802 } 00803 } 00804 00805 static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) 00806 { 00807 RenderResult *rr= pa->result; 00808 ShadeSample ssamp; 00809 intptr_t *rd, *rectdaps= pa->rectdaps; 00810 int samp; 00811 int x, y, seed, crop=0, offs=0, od; 00812 00813 if(R.test_break(R.tbh)) return; 00814 00815 /* irregular shadowb buffer creation */ 00816 if(R.r.mode & R_SHADOW) 00817 ISB_create(pa, NULL); 00818 00819 /* we set per pixel a fixed seed, for random AO and shadow samples */ 00820 seed= pa->rectx*pa->disprect.ymin; 00821 00822 /* general shader info, passes */ 00823 shade_sample_initialize(&ssamp, pa, rl); 00824 00825 /* occlusion caching */ 00826 if(R.occlusiontree) 00827 cache_occ_samples(&R, pa, &ssamp); 00828 00829 /* filtered render, for now we assume only 1 filter size */ 00830 if(pa->crop) { 00831 crop= 1; 00832 rectdaps+= pa->rectx + 1; 00833 offs= pa->rectx + 1; 00834 } 00835 00836 /* scanline updates have to be 2 lines behind */ 00837 rr->renrect.ymin= 0; 00838 rr->renrect.ymax= -2*crop; 00839 rr->renlay= rl; 00840 00841 for(y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++, rr->renrect.ymax++) { 00842 rd= rectdaps; 00843 od= offs; 00844 00845 for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, rd++, od++) { 00846 BLI_thread_srandom(pa->thread, seed++); 00847 00848 if(*rd) { 00849 if(shade_samples(&ssamp, (PixStr *)(*rd), x, y)) { 00850 00851 /* multisample buffers or filtered mask filling? */ 00852 if(pa->fullresult.first) { 00853 int a; 00854 for(samp=0; samp<ssamp.tot; samp++) { 00855 int smask= ssamp.shi[samp].mask; 00856 for(a=0; a<R.osa; a++) { 00857 int mask= 1<<a; 00858 if(smask & mask) 00859 add_passes(ssamp.rlpp[a], od, &ssamp.shi[samp], &ssamp.shr[samp]); 00860 } 00861 } 00862 } 00863 else { 00864 for(samp=0; samp<ssamp.tot; samp++) 00865 add_filt_passes(rl, ssamp.shi[samp].mask, pa->rectx, od, &ssamp.shi[samp], &ssamp.shr[samp]); 00866 } 00867 } 00868 } 00869 } 00870 00871 rectdaps+= pa->rectx; 00872 offs+= pa->rectx; 00873 00874 if(y&1) if(R.test_break(R.tbh)) break; 00875 } 00876 00877 /* disable scanline updating */ 00878 rr->renlay= NULL; 00879 00880 if(R.r.mode & R_SHADOW) 00881 ISB_free(pa); 00882 00883 if(R.occlusiontree) 00884 free_occ_samples(&R, pa); 00885 } 00886 00887 /* ************* pixel struct ******** */ 00888 00889 00890 static PixStrMain *addpsmain(ListBase *lb) 00891 { 00892 PixStrMain *psm; 00893 00894 psm= (PixStrMain *)MEM_mallocN(sizeof(PixStrMain),"pixstrMain"); 00895 BLI_addtail(lb, psm); 00896 00897 psm->ps= (PixStr *)MEM_mallocN(4096*sizeof(PixStr),"pixstr"); 00898 psm->counter= 0; 00899 00900 return psm; 00901 } 00902 00903 static void freeps(ListBase *lb) 00904 { 00905 PixStrMain *psm, *psmnext; 00906 00907 for(psm= lb->first; psm; psm= psmnext) { 00908 psmnext= psm->next; 00909 if(psm->ps) 00910 MEM_freeN(psm->ps); 00911 MEM_freeN(psm); 00912 } 00913 lb->first= lb->last= NULL; 00914 } 00915 00916 static void addps(ListBase *lb, intptr_t *rd, int obi, int facenr, int z, int maskz, unsigned short mask) 00917 { 00918 PixStrMain *psm; 00919 PixStr *ps, *last= NULL; 00920 00921 if(*rd) { 00922 ps= (PixStr *)(*rd); 00923 00924 while(ps) { 00925 if( ps->obi == obi && ps->facenr == facenr ) { 00926 ps->mask |= mask; 00927 return; 00928 } 00929 last= ps; 00930 ps= ps->next; 00931 } 00932 } 00933 00934 /* make new PS (pixel struct) */ 00935 psm= lb->last; 00936 00937 if(psm->counter==4095) 00938 psm= addpsmain(lb); 00939 00940 ps= psm->ps + psm->counter++; 00941 00942 if(last) last->next= ps; 00943 else *rd= (intptr_t)ps; 00944 00945 ps->next= NULL; 00946 ps->obi= obi; 00947 ps->facenr= facenr; 00948 ps->z= z; 00949 ps->maskz= maskz; 00950 ps->mask = mask; 00951 ps->shadfac= 0; 00952 } 00953 00954 static void edge_enhance_add(RenderPart *pa, float *rectf, float *arect) 00955 { 00956 float addcol[4]; 00957 int pix; 00958 00959 if(arect==NULL) 00960 return; 00961 00962 for(pix= pa->rectx*pa->recty; pix>0; pix--, arect++, rectf+=4) { 00963 if(*arect != 0.0f) { 00964 addcol[0]= *arect * R.r.edgeR; 00965 addcol[1]= *arect * R.r.edgeG; 00966 addcol[2]= *arect * R.r.edgeB; 00967 addcol[3]= *arect; 00968 addAlphaOverFloat(rectf, addcol); 00969 } 00970 } 00971 } 00972 00973 static void convert_to_key_alpha(RenderPart *pa, RenderLayer *rl) 00974 { 00975 RenderLayer *rlpp[RE_MAX_OSA]; 00976 int y, sample, totsample; 00977 00978 totsample= get_sample_layers(pa, rl, rlpp); 00979 00980 for(sample= 0; sample<totsample; sample++) { 00981 float *rectf= rlpp[sample]->rectf; 00982 00983 for(y= pa->rectx*pa->recty; y>0; y--, rectf+=4) { 00984 if(rectf[3] >= 1.0f); 00985 else if(rectf[3] > 0.0f) { 00986 rectf[0] /= rectf[3]; 00987 rectf[1] /= rectf[3]; 00988 rectf[2] /= rectf[3]; 00989 } 00990 } 00991 } 00992 } 00993 00994 /* adds only alpha values */ 00995 void edge_enhance_tile(RenderPart *pa, float *rectf, int *rectz) 00996 { 00997 /* use zbuffer to define edges, add it to the image */ 00998 int y, x, col, *rz, *rz1, *rz2, *rz3; 00999 int zval1, zval2, zval3; 01000 float *rf; 01001 01002 /* shift values in zbuffer 4 to the right (anti overflows), for filter we need multiplying with 12 max */ 01003 rz= rectz; 01004 if(rz==NULL) return; 01005 01006 for(y=0; y<pa->recty; y++) 01007 for(x=0; x<pa->rectx; x++, rz++) (*rz)>>= 4; 01008 01009 rz1= rectz; 01010 rz2= rz1+pa->rectx; 01011 rz3= rz2+pa->rectx; 01012 01013 rf= rectf+pa->rectx+1; 01014 01015 for(y=0; y<pa->recty-2; y++) { 01016 for(x=0; x<pa->rectx-2; x++, rz1++, rz2++, rz3++, rf++) { 01017 01018 /* prevent overflow with sky z values */ 01019 zval1= rz1[0] + 2*rz1[1] + rz1[2]; 01020 zval2= 2*rz2[0] + 2*rz2[2]; 01021 zval3= rz3[0] + 2*rz3[1] + rz3[2]; 01022 01023 col= ( 4*rz2[1] - (zval1 + zval2 + zval3)/3 ); 01024 if(col<0) col= -col; 01025 01026 col >>= 5; 01027 if(col > (1<<16)) col= (1<<16); 01028 else col= (R.r.edgeint*col)>>8; 01029 01030 if(col>0) { 01031 float fcol; 01032 01033 if(col>255) fcol= 1.0f; 01034 else fcol= (float)col/255.0f; 01035 01036 if(R.osa) 01037 *rf+= fcol/(float)R.osa; 01038 else 01039 *rf= fcol; 01040 } 01041 } 01042 rz1+= 2; 01043 rz2+= 2; 01044 rz3+= 2; 01045 rf+= 2; 01046 } 01047 01048 /* shift back zbuf values, we might need it still */ 01049 rz= rectz; 01050 for(y=0; y<pa->recty; y++) 01051 for(x=0; x<pa->rectx; x++, rz++) (*rz)<<= 4; 01052 01053 } 01054 01055 static void reset_sky_speed(RenderPart *pa, RenderLayer *rl) 01056 { 01057 /* for all pixels with max speed, set to zero */ 01058 RenderLayer *rlpp[RE_MAX_OSA]; 01059 float *fp; 01060 int a, sample, totsample; 01061 01062 totsample= get_sample_layers(pa, rl, rlpp); 01063 01064 for(sample= 0; sample<totsample; sample++) { 01065 fp= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_VECTOR); 01066 if(fp==NULL) break; 01067 01068 for(a= 4*pa->rectx*pa->recty - 1; a>=0; a--) 01069 if(fp[a] == PASS_VECTOR_MAX) fp[a]= 0.0f; 01070 } 01071 } 01072 01073 static unsigned short *make_solid_mask(RenderPart *pa) 01074 { 01075 intptr_t *rd= pa->rectdaps; 01076 unsigned short *solidmask, *sp; 01077 int x; 01078 01079 if(rd==NULL) return NULL; 01080 01081 sp=solidmask= MEM_mallocN(sizeof(short)*pa->rectx*pa->recty, "solidmask"); 01082 01083 for(x=pa->rectx*pa->recty; x>0; x--, rd++, sp++) { 01084 if(*rd) { 01085 PixStr *ps= (PixStr *)*rd; 01086 01087 *sp= ps->mask; 01088 for(ps= ps->next; ps; ps= ps->next) 01089 *sp |= ps->mask; 01090 } 01091 else 01092 *sp= 0; 01093 } 01094 01095 return solidmask; 01096 } 01097 01098 static void addAlphaOverFloatMask(float *dest, float *source, unsigned short dmask, unsigned short smask) 01099 { 01100 unsigned short shared= dmask & smask; 01101 float mul= 1.0 - source[3]; 01102 01103 if(shared) { /* overlapping masks */ 01104 01105 /* masks differ, we make a mixture of 'add' and 'over' */ 01106 if(shared!=dmask) { 01107 float shared_bits= (float)count_mask(shared); /* alpha over */ 01108 float tot_bits= (float)count_mask(smask|dmask); /* alpha add */ 01109 01110 float add= (tot_bits - shared_bits)/tot_bits; /* add level */ 01111 mul= add + (1.0f-add)*mul; 01112 } 01113 } 01114 else if(dmask && smask) { 01115 /* works for premul only, of course */ 01116 dest[0]+= source[0]; 01117 dest[1]+= source[1]; 01118 dest[2]+= source[2]; 01119 dest[3]+= source[3]; 01120 01121 return; 01122 } 01123 01124 dest[0]= (mul*dest[0]) + source[0]; 01125 dest[1]= (mul*dest[1]) + source[1]; 01126 dest[2]= (mul*dest[2]) + source[2]; 01127 dest[3]= (mul*dest[3]) + source[3]; 01128 } 01129 01130 typedef struct ZbufSolidData { 01131 RenderLayer *rl; 01132 ListBase *psmlist; 01133 float *edgerect; 01134 } ZbufSolidData; 01135 01136 void make_pixelstructs(RenderPart *pa, ZSpan *zspan, int sample, void *data) 01137 { 01138 ZbufSolidData *sdata= (ZbufSolidData*)data; 01139 ListBase *lb= sdata->psmlist; 01140 intptr_t *rd= pa->rectdaps; 01141 int *ro= zspan->recto; 01142 int *rp= zspan->rectp; 01143 int *rz= zspan->rectz; 01144 int *rm= zspan->rectmask; 01145 int x, y; 01146 int mask= 1<<sample; 01147 01148 for(y=0; y<pa->recty; y++) { 01149 for(x=0; x<pa->rectx; x++, rd++, rp++, ro++, rz++, rm++) { 01150 if(*rp) { 01151 addps(lb, rd, *ro, *rp, *rz, (zspan->rectmask)? *rm: 0, mask); 01152 } 01153 } 01154 } 01155 01156 if(sdata->rl->layflag & SCE_LAY_EDGE) 01157 if(R.r.mode & R_EDGE) 01158 edge_enhance_tile(pa, sdata->edgerect, zspan->rectz); 01159 } 01160 01161 /* main call for shading Delta Accum, for OSA */ 01162 /* supposed to be fully threadable! */ 01163 void zbufshadeDA_tile(RenderPart *pa) 01164 { 01165 RenderResult *rr= pa->result; 01166 RenderLayer *rl; 01167 ListBase psmlist= {NULL, NULL}; 01168 float *edgerect= NULL; 01169 01170 /* allocate the necessary buffers */ 01171 /* zbuffer inits these rects */ 01172 pa->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto"); 01173 pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp"); 01174 pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); 01175 for(rl= rr->layers.first; rl; rl= rl->next) { 01176 if((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK)) 01177 pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask"); 01178 01179 /* initialize pixelstructs and edge buffer */ 01180 addpsmain(&psmlist); 01181 pa->rectdaps= MEM_callocN(sizeof(intptr_t)*pa->rectx*pa->recty+4, "zbufDArectd"); 01182 01183 if(rl->layflag & SCE_LAY_EDGE) 01184 if(R.r.mode & R_EDGE) 01185 edgerect= MEM_callocN(sizeof(float)*pa->rectx*pa->recty, "rectedge"); 01186 01187 /* always fill visibility */ 01188 for(pa->sample=0; pa->sample<R.osa; pa->sample+=4) { 01189 ZbufSolidData sdata; 01190 01191 sdata.rl= rl; 01192 sdata.psmlist= &psmlist; 01193 sdata.edgerect= edgerect; 01194 zbuffer_solid(pa, rl, make_pixelstructs, &sdata); 01195 if(R.test_break(R.tbh)) break; 01196 } 01197 01198 /* shades solid */ 01199 if(rl->layflag & SCE_LAY_SOLID) 01200 shadeDA_tile(pa, rl); 01201 01202 /* lamphalo after solid, before ztra, looks nicest because ztra does own halo */ 01203 if(R.flag & R_LAMPHALO) 01204 if(rl->layflag & SCE_LAY_HALO) 01205 lamphalo_tile(pa, rl); 01206 01207 /* halo before ztra, because ztra fills in zbuffer now */ 01208 if(R.flag & R_HALO) 01209 if(rl->layflag & SCE_LAY_HALO) 01210 halo_tile(pa, rl); 01211 01212 /* transp layer */ 01213 if(R.flag & R_ZTRA || R.totstrand) { 01214 if(rl->layflag & (SCE_LAY_ZTRA|SCE_LAY_STRAND)) { 01215 if(pa->fullresult.first) { 01216 zbuffer_transp_shade(pa, rl, rl->rectf, &psmlist); 01217 } 01218 else { 01219 unsigned short *ztramask, *solidmask= NULL; /* 16 bits, MAX_OSA */ 01220 01221 /* allocate, but not free here, for asynchronous display of this rect in main thread */ 01222 rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer"); 01223 01224 /* swap for live updates, and it is used in zbuf.c!!! */ 01225 SWAP(float *, rl->acolrect, rl->rectf); 01226 ztramask= zbuffer_transp_shade(pa, rl, rl->rectf, &psmlist); 01227 SWAP(float *, rl->acolrect, rl->rectf); 01228 01229 /* zbuffer transp only returns ztramask if there's solid rendered */ 01230 if(ztramask) 01231 solidmask= make_solid_mask(pa); 01232 01233 if(ztramask && solidmask) { 01234 unsigned short *sps= solidmask, *spz= ztramask; 01235 unsigned short fullmask= (1<<R.osa)-1; 01236 float *fcol= rl->rectf; float *acol= rl->acolrect; 01237 int x; 01238 01239 for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4, sps++, spz++) { 01240 if(*sps == fullmask) 01241 addAlphaOverFloat(fcol, acol); 01242 else 01243 addAlphaOverFloatMask(fcol, acol, *sps, *spz); 01244 } 01245 } 01246 else { 01247 float *fcol= rl->rectf; float *acol= rl->acolrect; 01248 int x; 01249 for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) { 01250 addAlphaOverFloat(fcol, acol); 01251 } 01252 } 01253 if(solidmask) MEM_freeN(solidmask); 01254 if(ztramask) MEM_freeN(ztramask); 01255 } 01256 } 01257 } 01258 01259 /* sun/sky */ 01260 if(rl->layflag & SCE_LAY_SKY) 01261 atm_tile(pa, rl); 01262 01263 /* sky before edge */ 01264 if(rl->layflag & SCE_LAY_SKY) 01265 sky_tile(pa, rl); 01266 01267 /* extra layers */ 01268 if(rl->layflag & SCE_LAY_EDGE) 01269 if(R.r.mode & R_EDGE) 01270 edge_enhance_add(pa, rl->rectf, edgerect); 01271 01272 if(rl->passflag & SCE_PASS_VECTOR) 01273 reset_sky_speed(pa, rl); 01274 01275 /* de-premul alpha */ 01276 if(R.r.alphamode & R_ALPHAKEY) 01277 convert_to_key_alpha(pa, rl); 01278 01279 /* free stuff within loop! */ 01280 MEM_freeN(pa->rectdaps); pa->rectdaps= NULL; 01281 freeps(&psmlist); 01282 01283 if(edgerect) MEM_freeN(edgerect); 01284 edgerect= NULL; 01285 01286 if(pa->rectmask) { 01287 MEM_freeN(pa->rectmask); 01288 pa->rectmask= NULL; 01289 } 01290 } 01291 01292 /* free all */ 01293 MEM_freeN(pa->recto); pa->recto= NULL; 01294 MEM_freeN(pa->rectp); pa->rectp= NULL; 01295 MEM_freeN(pa->rectz); pa->rectz= NULL; 01296 01297 /* display active layer */ 01298 rr->renrect.ymin=rr->renrect.ymax= 0; 01299 rr->renlay= render_get_active_layer(&R, rr); 01300 } 01301 01302 01303 /* ------------------------------------------------------------------------ */ 01304 01305 /* non OSA case, full tile render */ 01306 /* supposed to be fully threadable! */ 01307 void zbufshade_tile(RenderPart *pa) 01308 { 01309 ShadeSample ssamp; 01310 RenderResult *rr= pa->result; 01311 RenderLayer *rl; 01312 PixStr ps; 01313 float *edgerect= NULL; 01314 01315 /* fake pixel struct, to comply to osa render */ 01316 ps.next= NULL; 01317 ps.mask= 0xFFFF; 01318 01319 /* zbuffer code clears/inits rects */ 01320 pa->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto"); 01321 pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp"); 01322 pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); 01323 01324 for(rl= rr->layers.first; rl; rl= rl->next) { 01325 if((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK)) 01326 pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask"); 01327 01328 /* general shader info, passes */ 01329 shade_sample_initialize(&ssamp, pa, rl); 01330 01331 zbuffer_solid(pa, rl, NULL, NULL); 01332 01333 if(!R.test_break(R.tbh)) { /* NOTE: this if() is not consistent */ 01334 01335 /* edges only for solid part, ztransp doesn't support it yet anti-aliased */ 01336 if(rl->layflag & SCE_LAY_EDGE) { 01337 if(R.r.mode & R_EDGE) { 01338 edgerect= MEM_callocN(sizeof(float)*pa->rectx*pa->recty, "rectedge"); 01339 edge_enhance_tile(pa, edgerect, pa->rectz); 01340 } 01341 } 01342 01343 /* initialize scanline updates for main thread */ 01344 rr->renrect.ymin= 0; 01345 rr->renlay= rl; 01346 01347 if(rl->layflag & SCE_LAY_SOLID) { 01348 float *fcol= rl->rectf; 01349 int *ro= pa->recto, *rp= pa->rectp, *rz= pa->rectz; 01350 int x, y, offs=0, seed; 01351 01352 /* we set per pixel a fixed seed, for random AO and shadow samples */ 01353 seed= pa->rectx*pa->disprect.ymin; 01354 01355 /* irregular shadowb buffer creation */ 01356 if(R.r.mode & R_SHADOW) 01357 ISB_create(pa, NULL); 01358 01359 if(R.occlusiontree) 01360 cache_occ_samples(&R, pa, &ssamp); 01361 01362 for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++, rr->renrect.ymax++) { 01363 for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, ro++, rz++, rp++, fcol+=4, offs++) { 01364 /* per pixel fixed seed */ 01365 BLI_thread_srandom(pa->thread, seed++); 01366 01367 if(*rp) { 01368 ps.obi= *ro; 01369 ps.facenr= *rp; 01370 ps.z= *rz; 01371 if(shade_samples(&ssamp, &ps, x, y)) { 01372 /* combined and passes */ 01373 add_passes(rl, offs, ssamp.shi, ssamp.shr); 01374 } 01375 } 01376 } 01377 if(y&1) 01378 if(R.test_break(R.tbh)) break; 01379 } 01380 01381 if(R.occlusiontree) 01382 free_occ_samples(&R, pa); 01383 01384 if(R.r.mode & R_SHADOW) 01385 ISB_free(pa); 01386 } 01387 01388 /* disable scanline updating */ 01389 rr->renlay= NULL; 01390 } 01391 01392 /* lamphalo after solid, before ztra, looks nicest because ztra does own halo */ 01393 if(R.flag & R_LAMPHALO) 01394 if(rl->layflag & SCE_LAY_HALO) 01395 lamphalo_tile(pa, rl); 01396 01397 /* halo before ztra, because ztra fills in zbuffer now */ 01398 if(R.flag & R_HALO) 01399 if(rl->layflag & SCE_LAY_HALO) 01400 halo_tile(pa, rl); 01401 01402 if(R.flag & R_ZTRA || R.totstrand) { 01403 if(rl->layflag & (SCE_LAY_ZTRA|SCE_LAY_STRAND)) { 01404 float *fcol, *acol; 01405 int x; 01406 01407 /* allocate, but not free here, for asynchronous display of this rect in main thread */ 01408 rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer"); 01409 01410 /* swap for live updates */ 01411 SWAP(float *, rl->acolrect, rl->rectf); 01412 zbuffer_transp_shade(pa, rl, rl->rectf, NULL); 01413 SWAP(float *, rl->acolrect, rl->rectf); 01414 01415 fcol= rl->rectf; acol= rl->acolrect; 01416 for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) { 01417 addAlphaOverFloat(fcol, acol); 01418 } 01419 } 01420 } 01421 01422 /* sun/sky */ 01423 if(rl->layflag & SCE_LAY_SKY) 01424 atm_tile(pa, rl); 01425 01426 /* sky before edge */ 01427 if(rl->layflag & SCE_LAY_SKY) 01428 sky_tile(pa, rl); 01429 01430 if(!R.test_break(R.tbh)) { 01431 if(rl->layflag & SCE_LAY_EDGE) 01432 if(R.r.mode & R_EDGE) 01433 edge_enhance_add(pa, rl->rectf, edgerect); 01434 } 01435 01436 if(rl->passflag & SCE_PASS_VECTOR) 01437 reset_sky_speed(pa, rl); 01438 01439 /* de-premul alpha */ 01440 if(R.r.alphamode & R_ALPHAKEY) 01441 convert_to_key_alpha(pa, rl); 01442 01443 if(edgerect) MEM_freeN(edgerect); 01444 edgerect= NULL; 01445 01446 if(pa->rectmask) { 01447 MEM_freeN(pa->rectmask); 01448 pa->rectmask= NULL; 01449 } 01450 } 01451 01452 /* display active layer */ 01453 rr->renrect.ymin=rr->renrect.ymax= 0; 01454 rr->renlay= render_get_active_layer(&R, rr); 01455 01456 MEM_freeN(pa->recto); pa->recto= NULL; 01457 MEM_freeN(pa->rectp); pa->rectp= NULL; 01458 MEM_freeN(pa->rectz); pa->rectz= NULL; 01459 } 01460 01461 /* SSS preprocess tile render, fully threadable */ 01462 typedef struct ZBufSSSHandle { 01463 RenderPart *pa; 01464 ListBase psmlist; 01465 int totps; 01466 } ZBufSSSHandle; 01467 01468 static void addps_sss(void *cb_handle, int obi, int facenr, int x, int y, int z) 01469 { 01470 ZBufSSSHandle *handle = cb_handle; 01471 RenderPart *pa= handle->pa; 01472 01473 /* extra border for filter gives double samples on part edges, 01474 don't use those */ 01475 if(x<pa->crop || x>=pa->rectx-pa->crop) 01476 return; 01477 if(y<pa->crop || y>=pa->recty-pa->crop) 01478 return; 01479 01480 if(pa->rectall) { 01481 intptr_t *rs= pa->rectall + pa->rectx*y + x; 01482 01483 addps(&handle->psmlist, rs, obi, facenr, z, 0, 0); 01484 handle->totps++; 01485 } 01486 if(pa->rectz) { 01487 int *rz= pa->rectz + pa->rectx*y + x; 01488 int *rp= pa->rectp + pa->rectx*y + x; 01489 int *ro= pa->recto + pa->rectx*y + x; 01490 01491 if(z < *rz) { 01492 if(*rp == 0) 01493 handle->totps++; 01494 *rz= z; 01495 *rp= facenr; 01496 *ro= obi; 01497 } 01498 } 01499 if(pa->rectbackz) { 01500 int *rz= pa->rectbackz + pa->rectx*y + x; 01501 int *rp= pa->rectbackp + pa->rectx*y + x; 01502 int *ro= pa->rectbacko + pa->rectx*y + x; 01503 01504 if(z >= *rz) { 01505 if(*rp == 0) 01506 handle->totps++; 01507 *rz= z; 01508 *rp= facenr; 01509 *ro= obi; 01510 } 01511 } 01512 } 01513 01514 static void shade_sample_sss(ShadeSample *ssamp, Material *mat, ObjectInstanceRen *obi, VlakRen *vlr, int quad, float x, float y, float z, float *co, float *color, float *area) 01515 { 01516 ShadeInput *shi= ssamp->shi; 01517 ShadeResult shr; 01518 float texfac, orthoarea, nor[3], alpha, sx, sy; 01519 01520 /* cache for shadow */ 01521 shi->samplenr= R.shadowsamplenr[shi->thread]++; 01522 01523 if(quad) 01524 shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3); 01525 else 01526 shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2); 01527 01528 /* center pixel */ 01529 sx = x + 0.5f; 01530 sy = y + 0.5f; 01531 01532 /* we estimate the area here using shi->dxco and shi->dyco. we need to 01533 enabled shi->osatex these are filled. we compute two areas, one with 01534 the normal pointed at the camera and one with the original normal, and 01535 then clamp to avoid a too large contribution from a single pixel */ 01536 shi->osatex= 1; 01537 01538 VECCOPY(nor, shi->facenor); 01539 calc_view_vector(shi->facenor, sx, sy); 01540 normalize_v3(shi->facenor); 01541 shade_input_set_viewco(shi, x, y, sx, sy, z); 01542 orthoarea= len_v3(shi->dxco)*len_v3(shi->dyco); 01543 01544 VECCOPY(shi->facenor, nor); 01545 shade_input_set_viewco(shi, x, y, sx, sy, z); 01546 *area= len_v3(shi->dxco)*len_v3(shi->dyco); 01547 *area= MIN2(*area, 2.0f*orthoarea); 01548 01549 shade_input_set_uv(shi); 01550 shade_input_set_normals(shi); 01551 01552 /* we don't want flipped normals, they screw up back scattering */ 01553 if(shi->flippednor) 01554 shade_input_flip_normals(shi); 01555 01556 /* not a pretty solution, but fixes common cases */ 01557 if(shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) { 01558 negate_v3(shi->vn); 01559 negate_v3(shi->vno); 01560 negate_v3(shi->nmapnorm); 01561 } 01562 01563 /* if nodetree, use the material that we are currently preprocessing 01564 instead of the node material */ 01565 if(shi->mat->nodetree && shi->mat->use_nodes) 01566 shi->mat= mat; 01567 01568 /* init material vars */ 01569 shade_input_init_material(shi); 01570 01571 /* render */ 01572 shade_input_set_shade_texco(shi); 01573 01574 shade_samples_do_AO(ssamp); 01575 shade_material_loop(shi, &shr); 01576 01577 VECCOPY(co, shi->co); 01578 VECCOPY(color, shr.combined); 01579 01580 /* texture blending */ 01581 texfac= shi->mat->sss_texfac; 01582 01583 alpha= shr.combined[3]; 01584 *area *= alpha; 01585 } 01586 01587 static void zbufshade_sss_free(RenderPart *pa) 01588 { 01589 #if 0 01590 MEM_freeN(pa->rectall); pa->rectall= NULL; 01591 freeps(&handle.psmlist); 01592 #else 01593 MEM_freeN(pa->rectz); pa->rectz= NULL; 01594 MEM_freeN(pa->rectp); pa->rectp= NULL; 01595 MEM_freeN(pa->recto); pa->recto= NULL; 01596 MEM_freeN(pa->rectbackz); pa->rectbackz= NULL; 01597 MEM_freeN(pa->rectbackp); pa->rectbackp= NULL; 01598 MEM_freeN(pa->rectbacko); pa->rectbacko= NULL; 01599 #endif 01600 } 01601 01602 void zbufshade_sss_tile(RenderPart *pa) 01603 { 01604 Render *re= &R; 01605 ShadeSample ssamp; 01606 ZBufSSSHandle handle; 01607 RenderResult *rr= pa->result; 01608 RenderLayer *rl; 01609 VlakRen *vlr; 01610 Material *mat= re->sss_mat; 01611 float (*co)[3], (*color)[3], *area, *fcol; 01612 int x, y, seed, quad, totpoint, display = !(re->r.scemode & R_PREVIEWBUTS); 01613 int *ro, *rz, *rp, *rbo, *rbz, *rbp, lay; 01614 #if 0 01615 PixStr *ps; 01616 intptr_t *rs; 01617 int z; 01618 #endif 01619 01620 /* setup pixelstr list and buffer for zbuffering */ 01621 handle.pa= pa; 01622 handle.totps= 0; 01623 01624 #if 0 01625 handle.psmlist.first= handle.psmlist.last= NULL; 01626 addpsmain(&handle.psmlist); 01627 01628 pa->rectall= MEM_callocN(sizeof(intptr_t)*pa->rectx*pa->recty+4, "rectall"); 01629 #else 01630 pa->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto"); 01631 pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp"); 01632 pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); 01633 pa->rectbacko= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbacko"); 01634 pa->rectbackp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbackp"); 01635 pa->rectbackz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbackz"); 01636 #endif 01637 01638 /* setup shade sample with correct passes */ 01639 memset(&ssamp, 0, sizeof(ssamp)); 01640 shade_sample_initialize(&ssamp, pa, rr->layers.first); 01641 ssamp.tot= 1; 01642 01643 for(rl=rr->layers.first; rl; rl=rl->next) { 01644 ssamp.shi[0].lay |= rl->lay; 01645 ssamp.shi[0].layflag |= rl->layflag; 01646 ssamp.shi[0].passflag |= rl->passflag; 01647 ssamp.shi[0].combinedflag |= ~rl->pass_xor; 01648 } 01649 01650 rl= rr->layers.first; 01651 ssamp.shi[0].passflag |= SCE_PASS_RGBA|SCE_PASS_COMBINED; 01652 ssamp.shi[0].combinedflag &= ~(SCE_PASS_SPEC); 01653 ssamp.shi[0].mat_override= NULL; 01654 ssamp.shi[0].light_override= NULL; 01655 lay= ssamp.shi[0].lay; 01656 01657 /* create the pixelstrs to be used later */ 01658 zbuffer_sss(pa, lay, &handle, addps_sss); 01659 01660 if(handle.totps==0) { 01661 zbufshade_sss_free(pa); 01662 return; 01663 } 01664 01665 fcol= rl->rectf; 01666 01667 co= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSCo"); 01668 color= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSColor"); 01669 area= MEM_mallocN(sizeof(float)*handle.totps, "SSSArea"); 01670 01671 #if 0 01672 /* create ISB (does not work currently!) */ 01673 if(re->r.mode & R_SHADOW) 01674 ISB_create(pa, NULL); 01675 #endif 01676 01677 if(display) { 01678 /* initialize scanline updates for main thread */ 01679 rr->renrect.ymin= 0; 01680 rr->renlay= rl; 01681 } 01682 01683 seed= pa->rectx*pa->disprect.ymin; 01684 #if 0 01685 rs= pa->rectall; 01686 #else 01687 rz= pa->rectz; 01688 rp= pa->rectp; 01689 ro= pa->recto; 01690 rbz= pa->rectbackz; 01691 rbp= pa->rectbackp; 01692 rbo= pa->rectbacko; 01693 #endif 01694 totpoint= 0; 01695 01696 for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++, rr->renrect.ymax++) { 01697 for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, fcol+=4) { 01698 /* per pixel fixed seed */ 01699 BLI_thread_srandom(pa->thread, seed++); 01700 01701 #if 0 01702 if(rs) { 01703 /* for each sample in this pixel, shade it */ 01704 for(ps=(PixStr*)*rs; ps; ps=ps->next) { 01705 ObjectInstanceRen *obi= &re->objectinstance[ps->obi]; 01706 ObjectRen *obr= obi->obr; 01707 vlr= RE_findOrAddVlak(obr, (ps->facenr-1) & RE_QUAD_MASK); 01708 quad= (ps->facenr & RE_QUAD_OFFS); 01709 z= ps->z; 01710 01711 shade_sample_sss(&ssamp, mat, obi, vlr, quad, x, y, z, 01712 co[totpoint], color[totpoint], &area[totpoint]); 01713 01714 totpoint++; 01715 01716 VECADD(fcol, fcol, color); 01717 fcol[3]= 1.0f; 01718 } 01719 01720 rs++; 01721 } 01722 #else 01723 if(rp) { 01724 if(*rp != 0) { 01725 ObjectInstanceRen *obi= &re->objectinstance[*ro]; 01726 ObjectRen *obr= obi->obr; 01727 01728 /* shade front */ 01729 vlr= RE_findOrAddVlak(obr, (*rp-1) & RE_QUAD_MASK); 01730 quad= ((*rp) & RE_QUAD_OFFS); 01731 01732 shade_sample_sss(&ssamp, mat, obi, vlr, quad, x, y, *rz, 01733 co[totpoint], color[totpoint], &area[totpoint]); 01734 01735 VECADD(fcol, fcol, color[totpoint]); 01736 fcol[3]= 1.0f; 01737 totpoint++; 01738 } 01739 01740 rp++; rz++; ro++; 01741 } 01742 01743 if(rbp) { 01744 if(*rbp != 0 && !(*rbp == *(rp-1) && *rbo == *(ro-1))) { 01745 ObjectInstanceRen *obi= &re->objectinstance[*rbo]; 01746 ObjectRen *obr= obi->obr; 01747 01748 /* shade back */ 01749 vlr= RE_findOrAddVlak(obr, (*rbp-1) & RE_QUAD_MASK); 01750 quad= ((*rbp) & RE_QUAD_OFFS); 01751 01752 shade_sample_sss(&ssamp, mat, obi, vlr, quad, x, y, *rbz, 01753 co[totpoint], color[totpoint], &area[totpoint]); 01754 01755 /* to indicate this is a back sample */ 01756 area[totpoint]= -area[totpoint]; 01757 01758 VECADD(fcol, fcol, color[totpoint]); 01759 fcol[3]= 1.0f; 01760 totpoint++; 01761 } 01762 01763 rbz++; rbp++; rbo++; 01764 } 01765 #endif 01766 } 01767 01768 if(y&1) 01769 if(re->test_break(re->tbh)) break; 01770 } 01771 01772 /* note: after adding we do not free these arrays, sss keeps them */ 01773 if(totpoint > 0) { 01774 sss_add_points(re, co, color, area, totpoint); 01775 } 01776 else { 01777 MEM_freeN(co); 01778 MEM_freeN(color); 01779 MEM_freeN(area); 01780 } 01781 01782 #if 0 01783 if(re->r.mode & R_SHADOW) 01784 ISB_free(pa); 01785 #endif 01786 01787 if(display) { 01788 /* display active layer */ 01789 rr->renrect.ymin=rr->renrect.ymax= 0; 01790 rr->renlay= render_get_active_layer(&R, rr); 01791 } 01792 01793 zbufshade_sss_free(pa); 01794 } 01795 01796 /* ------------------------------------------------------------------------ */ 01797 01798 static void renderhalo_post(RenderResult *rr, float *rectf, HaloRen *har) /* postprocess version */ 01799 { 01800 float dist, xsq, ysq, xn, yn, colf[4], *rectft, *rtf; 01801 float haloxs, haloys; 01802 int minx, maxx, miny, maxy, x, y; 01803 01804 /* calculate the disprect mapped coordinate for halo. note: rectx is disprect corrected */ 01805 haloxs= har->xs - R.disprect.xmin; 01806 haloys= har->ys - R.disprect.ymin; 01807 01808 har->miny= miny= haloys - har->rad/R.ycor; 01809 har->maxy= maxy= haloys + har->rad/R.ycor; 01810 01811 if(maxy<0); 01812 else if(rr->recty<miny); 01813 else { 01814 minx= floor(haloxs-har->rad); 01815 maxx= ceil(haloxs+har->rad); 01816 01817 if(maxx<0); 01818 else if(rr->rectx<minx); 01819 else { 01820 01821 if(minx<0) minx= 0; 01822 if(maxx>=rr->rectx) maxx= rr->rectx-1; 01823 if(miny<0) miny= 0; 01824 if(maxy>rr->recty) maxy= rr->recty; 01825 01826 rectft= rectf+ 4*rr->rectx*miny; 01827 01828 for(y=miny; y<maxy; y++) { 01829 01830 rtf= rectft+4*minx; 01831 01832 yn= (y - haloys)*R.ycor; 01833 ysq= yn*yn; 01834 01835 for(x=minx; x<=maxx; x++) { 01836 xn= x - haloxs; 01837 xsq= xn*xn; 01838 dist= xsq+ysq; 01839 if(dist<har->radsq) { 01840 01841 if(shadeHaloFloat(har, colf, 0x7FFFFF, dist, xn, yn, har->flarec)) 01842 addalphaAddfacFloat(rtf, colf, har->add); 01843 } 01844 rtf+=4; 01845 } 01846 01847 rectft+= 4*rr->rectx; 01848 01849 if(R.test_break(R.tbh)) break; 01850 } 01851 } 01852 } 01853 } 01854 /* ------------------------------------------------------------------------ */ 01855 01856 static void renderflare(RenderResult *rr, float *rectf, HaloRen *har) 01857 { 01858 extern float hashvectf[]; 01859 HaloRen fla; 01860 Material *ma; 01861 float *rc, rad, alfa, visifac, vec[3]; 01862 int b, type; 01863 01864 fla= *har; 01865 fla.linec= fla.ringc= fla.flarec= 0; 01866 01867 rad= har->rad; 01868 alfa= har->alfa; 01869 01870 visifac= R.ycor*(har->pixels); 01871 /* all radials added / r^3 == 1.0f! */ 01872 visifac /= (har->rad*har->rad*har->rad); 01873 visifac*= visifac; 01874 01875 ma= har->mat; 01876 01877 /* first halo: just do */ 01878 01879 har->rad= rad*ma->flaresize*visifac; 01880 har->radsq= har->rad*har->rad; 01881 har->zs= fla.zs= 0; 01882 01883 har->alfa= alfa*visifac; 01884 01885 renderhalo_post(rr, rectf, har); 01886 01887 /* next halo's: the flares */ 01888 rc= hashvectf + ma->seed2; 01889 01890 for(b=1; b<har->flarec; b++) { 01891 01892 fla.r= fabs(rc[0]); 01893 fla.g= fabs(rc[1]); 01894 fla.b= fabs(rc[2]); 01895 fla.alfa= ma->flareboost*fabs(alfa*visifac*rc[3]); 01896 fla.hard= 20.0f + fabs(70*rc[7]); 01897 fla.tex= 0; 01898 01899 type= (int)(fabs(3.9*rc[6])); 01900 01901 fla.rad= ma->subsize*sqrt(fabs(2.0f*har->rad*rc[4])); 01902 01903 if(type==3) { 01904 fla.rad*= 3.0f; 01905 fla.rad+= R.rectx/10; 01906 } 01907 01908 fla.radsq= fla.rad*fla.rad; 01909 01910 vec[0]= 1.4*rc[5]*(har->xs-R.winx/2); 01911 vec[1]= 1.4*rc[5]*(har->ys-R.winy/2); 01912 vec[2]= 32.0f*sqrt(vec[0]*vec[0] + vec[1]*vec[1] + 1.0f); 01913 01914 fla.xs= R.winx/2 + vec[0] + (1.2+rc[8])*R.rectx*vec[0]/vec[2]; 01915 fla.ys= R.winy/2 + vec[1] + (1.2+rc[8])*R.rectx*vec[1]/vec[2]; 01916 01917 if(R.flag & R_SEC_FIELD) { 01918 if(R.r.mode & R_ODDFIELD) fla.ys += 0.5; 01919 else fla.ys -= 0.5; 01920 } 01921 if(type & 1) fla.type= HA_FLARECIRC; 01922 else fla.type= 0; 01923 renderhalo_post(rr, rectf, &fla); 01924 01925 fla.alfa*= 0.5; 01926 if(type & 2) fla.type= HA_FLARECIRC; 01927 else fla.type= 0; 01928 renderhalo_post(rr, rectf, &fla); 01929 01930 rc+= 7; 01931 } 01932 } 01933 01934 /* needs recode... integrate this better! */ 01935 void add_halo_flare(Render *re) 01936 { 01937 RenderResult *rr= re->result; 01938 RenderLayer *rl; 01939 HaloRen *har; 01940 int a, mode, do_draw=0; 01941 01942 /* for now, we get the first renderlayer in list with halos set */ 01943 for(rl= rr->layers.first; rl; rl= rl->next) 01944 if(rl->layflag & SCE_LAY_HALO) 01945 break; 01946 01947 if(rl==NULL || rl->rectf==NULL) 01948 return; 01949 01950 mode= R.r.mode; 01951 R.r.mode &= ~R_PANORAMA; 01952 01953 project_renderdata(&R, projectverto, 0, 0, 0); 01954 01955 for(a=0; a<R.tothalo; a++) { 01956 har= R.sortedhalos[a]; 01957 01958 if(har->flarec) { 01959 do_draw= 1; 01960 renderflare(rr, rl->rectf, har); 01961 } 01962 } 01963 01964 if(do_draw) { 01965 /* weak... the display callback wants an active renderlayer pointer... */ 01966 rr->renlay= rl; 01967 re->display_draw(re->ddh, rr, NULL); 01968 } 01969 01970 R.r.mode= mode; 01971 } 01972 01973 /* ************************* bake ************************ */ 01974 01975 01976 typedef struct BakeShade { 01977 ShadeSample ssamp; 01978 ObjectInstanceRen *obi; 01979 VlakRen *vlr; 01980 01981 ZSpan *zspan; 01982 Image *ima; 01983 ImBuf *ibuf; 01984 01985 int rectx, recty, quad, type, vdone, ready; 01986 01987 float dir[3]; 01988 Object *actob; 01989 01990 unsigned int *rect; 01991 float *rect_float; 01992 01993 int usemask; 01994 char *rect_mask; /* bake pixel mask */ 01995 01996 float dxco[3], dyco[3]; 01997 01998 short *do_update; 01999 } BakeShade; 02000 02001 static void bake_set_shade_input(ObjectInstanceRen *obi, VlakRen *vlr, ShadeInput *shi, int quad, int UNUSED(isect), int x, int y, float u, float v) 02002 { 02003 if(quad) 02004 shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3); 02005 else 02006 shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2); 02007 02008 /* cache for shadow */ 02009 shi->samplenr= R.shadowsamplenr[shi->thread]++; 02010 02011 shi->mask= 0xFFFF; /* all samples */ 02012 02013 shi->u= -u; 02014 shi->v= -v; 02015 shi->xs= x; 02016 shi->ys= y; 02017 02018 shade_input_set_uv(shi); 02019 shade_input_set_normals(shi); 02020 02021 /* no normal flip */ 02022 if(shi->flippednor) 02023 shade_input_flip_normals(shi); 02024 02025 /* set up view vector to look right at the surface (note that the normal 02026 * is negated in the renderer so it does not need to be done here) */ 02027 shi->view[0]= shi->vn[0]; 02028 shi->view[1]= shi->vn[1]; 02029 shi->view[2]= shi->vn[2]; 02030 } 02031 02032 static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(quad), int x, int y, float UNUSED(u), float UNUSED(v), float *tvn, float *ttang) 02033 { 02034 BakeShade *bs= handle; 02035 ShadeSample *ssamp= &bs->ssamp; 02036 ShadeResult shr; 02037 VlakRen *vlr= shi->vlr; 02038 02039 shade_input_init_material(shi); 02040 02041 if(bs->type==RE_BAKE_AO) { 02042 ambient_occlusion(shi); 02043 02044 if(R.r.bake_flag & R_BAKE_NORMALIZE) { 02045 copy_v3_v3(shr.combined, shi->ao); 02046 } 02047 else { 02048 zero_v3(shr.combined); 02049 environment_lighting_apply(shi, &shr); 02050 } 02051 } 02052 else { 02053 if (bs->type==RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */ 02054 shi->r = shi->g = shi->b = 1.0f; 02055 02056 shade_input_set_shade_texco(shi); 02057 02058 /* only do AO for a full bake (and obviously AO bakes) 02059 AO for light bakes is a leftover and might not be needed */ 02060 if( ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_AO, RE_BAKE_LIGHT)) 02061 shade_samples_do_AO(ssamp); 02062 02063 if(shi->mat->nodetree && shi->mat->use_nodes) { 02064 ntreeShaderExecTree(shi->mat->nodetree, shi, &shr); 02065 shi->mat= vlr->mat; /* shi->mat is being set in nodetree */ 02066 } 02067 else 02068 shade_material_loop(shi, &shr); 02069 02070 if(bs->type==RE_BAKE_NORMALS) { 02071 float nor[3]; 02072 02073 VECCOPY(nor, shi->vn); 02074 02075 if(R.r.bake_normal_space == R_BAKE_SPACE_CAMERA); 02076 else if(R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) { 02077 float mat[3][3], imat[3][3]; 02078 02079 /* bitangent */ 02080 if(tvn && ttang) { 02081 VECCOPY(mat[0], ttang); 02082 cross_v3_v3v3(mat[1], tvn, ttang); 02083 mul_v3_fl(mat[1], ttang[3]); 02084 VECCOPY(mat[2], tvn); 02085 } 02086 else { 02087 VECCOPY(mat[0], shi->nmaptang); 02088 cross_v3_v3v3(mat[1], shi->nmapnorm, shi->nmaptang); 02089 mul_v3_fl(mat[1], shi->nmaptang[3]); 02090 VECCOPY(mat[2], shi->nmapnorm); 02091 } 02092 02093 invert_m3_m3(imat, mat); 02094 mul_m3_v3(imat, nor); 02095 } 02096 else if(R.r.bake_normal_space == R_BAKE_SPACE_OBJECT) 02097 mul_mat3_m4_v3(ob->imat_ren, nor); /* ob->imat_ren includes viewinv! */ 02098 else if(R.r.bake_normal_space == R_BAKE_SPACE_WORLD) 02099 mul_mat3_m4_v3(R.viewinv, nor); 02100 02101 normalize_v3(nor); /* in case object has scaling */ 02102 02103 // The invert of the red channel is to make 02104 // the normal map compliant with the outside world. 02105 // It needs to be done because in Blender 02106 // the normal used in the renderer points inward. It is generated 02107 // this way in calc_vertexnormals(). Should this ever change 02108 // this negate must be removed. 02109 shr.combined[0]= (-nor[0])/2.0f + 0.5f; 02110 shr.combined[1]= nor[1]/2.0f + 0.5f; 02111 shr.combined[2]= nor[2]/2.0f + 0.5f; 02112 } 02113 else if(bs->type==RE_BAKE_TEXTURE) { 02114 shr.combined[0]= shi->r; 02115 shr.combined[1]= shi->g; 02116 shr.combined[2]= shi->b; 02117 shr.alpha = shi->alpha; 02118 } 02119 else if(bs->type==RE_BAKE_SHADOW) { 02120 VECCOPY(shr.combined, shr.shad); 02121 shr.alpha = shi->alpha; 02122 } 02123 else if(bs->type==RE_BAKE_SPEC_COLOR) { 02124 shr.combined[0]= shi->specr; 02125 shr.combined[1]= shi->specg; 02126 shr.combined[2]= shi->specb; 02127 shr.alpha = 1.0f; 02128 } 02129 else if(bs->type==RE_BAKE_SPEC_INTENSITY) { 02130 shr.combined[0]= 02131 shr.combined[1]= 02132 shr.combined[2]= shi->spec; 02133 shr.alpha = 1.0f; 02134 } 02135 else if(bs->type==RE_BAKE_MIRROR_COLOR) { 02136 shr.combined[0]= shi->mirr; 02137 shr.combined[1]= shi->mirg; 02138 shr.combined[2]= shi->mirb; 02139 shr.alpha = 1.0f; 02140 } 02141 else if(bs->type==RE_BAKE_MIRROR_INTENSITY) { 02142 shr.combined[0]= 02143 shr.combined[1]= 02144 shr.combined[2]= shi->ray_mirror; 02145 shr.alpha = 1.0f; 02146 } 02147 else if(bs->type==RE_BAKE_ALPHA) { 02148 shr.combined[0]= 02149 shr.combined[1]= 02150 shr.combined[2]= shi->alpha; 02151 shr.alpha = 1.0f; 02152 } 02153 else if(bs->type==RE_BAKE_EMIT) { 02154 shr.combined[0]= 02155 shr.combined[1]= 02156 shr.combined[2]= shi->emit; 02157 shr.alpha = 1.0f; 02158 } 02159 } 02160 02161 if(bs->rect_float) { 02162 float *col= bs->rect_float + 4*(bs->rectx*y + x); 02163 VECCOPY(col, shr.combined); 02164 if (bs->type==RE_BAKE_ALL || bs->type==RE_BAKE_TEXTURE) { 02165 col[3]= shr.alpha; 02166 } else { 02167 col[3]= 1.0; 02168 } 02169 } 02170 else { 02171 char *col= (char *)(bs->rect + bs->rectx*y + x); 02172 02173 if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE) && (R.r.color_mgt_flag & R_COLOR_MANAGEMENT)) { 02174 float srgb[3]; 02175 srgb[0]= linearrgb_to_srgb(shr.combined[0]); 02176 srgb[1]= linearrgb_to_srgb(shr.combined[1]); 02177 srgb[2]= linearrgb_to_srgb(shr.combined[2]); 02178 02179 col[0]= FTOCHAR(srgb[0]); 02180 col[1]= FTOCHAR(srgb[1]); 02181 col[2]= FTOCHAR(srgb[2]); 02182 } else { 02183 col[0]= FTOCHAR(shr.combined[0]); 02184 col[1]= FTOCHAR(shr.combined[1]); 02185 col[2]= FTOCHAR(shr.combined[2]); 02186 } 02187 02188 if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) { 02189 col[3]= FTOCHAR(shr.alpha); 02190 } else { 02191 col[3]= 255; 02192 } 02193 } 02194 02195 if (bs->rect_mask) { 02196 bs->rect_mask[bs->rectx*y + x] = FILTER_MASK_USED; 02197 } 02198 } 02199 02200 static void bake_displacement(void *handle, ShadeInput *UNUSED(shi), float dist, int x, int y) 02201 { 02202 BakeShade *bs= handle; 02203 float disp; 02204 02205 if(R.r.bake_flag & R_BAKE_NORMALIZE && R.r.bake_maxdist) { 02206 disp = (dist+R.r.bake_maxdist) / (R.r.bake_maxdist*2); /* alter the range from [-bake_maxdist, bake_maxdist] to [0, 1]*/ 02207 } else { 02208 disp = 0.5 + dist; /* alter the range from [-0.5,0.5] to [0,1]*/ 02209 } 02210 02211 if(bs->rect_float) { 02212 float *col= bs->rect_float + 4*(bs->rectx*y + x); 02213 col[0] = col[1] = col[2] = disp; 02214 col[3]= 1.0f; 02215 } else { 02216 char *col= (char *)(bs->rect + bs->rectx*y + x); 02217 col[0]= FTOCHAR(disp); 02218 col[1]= FTOCHAR(disp); 02219 col[2]= FTOCHAR(disp); 02220 col[3]= 255; 02221 } 02222 if (bs->rect_mask) { 02223 bs->rect_mask[bs->rectx*y + x] = FILTER_MASK_USED; 02224 } 02225 } 02226 02227 static int bake_intersect_tree(RayObject* raytree, Isect* isect, float *start, float *dir, float sign, float *hitco, float *dist) 02228 { 02229 float maxdist; 02230 int hit; 02231 02232 /* might be useful to make a user setting for maxsize*/ 02233 if(R.r.bake_maxdist > 0.0f) 02234 maxdist= R.r.bake_maxdist; 02235 else 02236 maxdist= RE_RAYTRACE_MAXDIST + R.r.bake_biasdist; 02237 02238 /* 'dir' is always normalized */ 02239 VECADDFAC(isect->start, start, dir, -R.r.bake_biasdist); 02240 02241 isect->dir[0] = dir[0]*sign; 02242 isect->dir[1] = dir[1]*sign; 02243 isect->dir[2] = dir[2]*sign; 02244 02245 isect->dist = maxdist; 02246 02247 hit = RE_rayobject_raycast(raytree, isect); 02248 if(hit) { 02249 hitco[0] = isect->start[0] + isect->dist*isect->dir[0]; 02250 hitco[1] = isect->start[1] + isect->dist*isect->dir[1]; 02251 hitco[2] = isect->start[2] + isect->dist*isect->dir[2]; 02252 02253 *dist= isect->dist; 02254 } 02255 02256 return hit; 02257 } 02258 02259 static void bake_set_vlr_dxyco(BakeShade *bs, float *uv1, float *uv2, float *uv3) 02260 { 02261 VlakRen *vlr= bs->vlr; 02262 float A, d1, d2, d3, *v1, *v2, *v3; 02263 02264 if(bs->quad) { 02265 v1= vlr->v1->co; 02266 v2= vlr->v3->co; 02267 v3= vlr->v4->co; 02268 } 02269 else { 02270 v1= vlr->v1->co; 02271 v2= vlr->v2->co; 02272 v3= vlr->v3->co; 02273 } 02274 02275 /* formula derived from barycentric coordinates: 02276 * (uvArea1*v1 + uvArea2*v2 + uvArea3*v3)/uvArea 02277 * then taking u and v partial derivatives to get dxco and dyco */ 02278 A= (uv2[0] - uv1[0])*(uv3[1] - uv1[1]) - (uv3[0] - uv1[0])*(uv2[1] - uv1[1]); 02279 02280 if(fabs(A) > FLT_EPSILON) { 02281 A= 0.5f/A; 02282 02283 d1= uv2[1] - uv3[1]; 02284 d2= uv3[1] - uv1[1]; 02285 d3= uv1[1] - uv2[1]; 02286 bs->dxco[0]= (v1[0]*d1 + v2[0]*d2 + v3[0]*d3)*A; 02287 bs->dxco[1]= (v1[1]*d1 + v2[1]*d2 + v3[1]*d3)*A; 02288 bs->dxco[2]= (v1[2]*d1 + v2[2]*d2 + v3[2]*d3)*A; 02289 02290 d1= uv3[0] - uv2[0]; 02291 d2= uv1[0] - uv3[0]; 02292 d3= uv2[0] - uv1[0]; 02293 bs->dyco[0]= (v1[0]*d1 + v2[0]*d2 + v3[0]*d3)*A; 02294 bs->dyco[1]= (v1[1]*d1 + v2[1]*d2 + v3[1]*d3)*A; 02295 bs->dyco[2]= (v1[2]*d1 + v2[2]*d2 + v3[2]*d3)*A; 02296 } 02297 else { 02298 bs->dxco[0]= bs->dxco[1]= bs->dxco[2]= 0.0f; 02299 bs->dyco[0]= bs->dyco[1]= bs->dyco[2]= 0.0f; 02300 } 02301 02302 if(bs->obi->flag & R_TRANSFORMED) { 02303 mul_m3_v3(bs->obi->nmat, bs->dxco); 02304 mul_m3_v3(bs->obi->nmat, bs->dyco); 02305 } 02306 } 02307 02308 static void do_bake_shade(void *handle, int x, int y, float u, float v) 02309 { 02310 BakeShade *bs= handle; 02311 VlakRen *vlr= bs->vlr; 02312 ObjectInstanceRen *obi= bs->obi; 02313 Object *ob= obi->obr->ob; 02314 float l, *v1, *v2, *v3, tvn[3], ttang[4]; 02315 int quad; 02316 ShadeSample *ssamp= &bs->ssamp; 02317 ShadeInput *shi= ssamp->shi; 02318 02319 /* fast threadsafe break test */ 02320 if(R.test_break(R.tbh)) 02321 return; 02322 02323 /* setup render coordinates */ 02324 if(bs->quad) { 02325 v1= vlr->v1->co; 02326 v2= vlr->v3->co; 02327 v3= vlr->v4->co; 02328 } 02329 else { 02330 v1= vlr->v1->co; 02331 v2= vlr->v2->co; 02332 v3= vlr->v3->co; 02333 } 02334 02335 /* renderco */ 02336 l= 1.0f-u-v; 02337 02338 shi->co[0]= l*v3[0]+u*v1[0]+v*v2[0]; 02339 shi->co[1]= l*v3[1]+u*v1[1]+v*v2[1]; 02340 shi->co[2]= l*v3[2]+u*v1[2]+v*v2[2]; 02341 02342 if(obi->flag & R_TRANSFORMED) 02343 mul_m4_v3(obi->mat, shi->co); 02344 02345 VECCOPY(shi->dxco, bs->dxco); 02346 VECCOPY(shi->dyco, bs->dyco); 02347 02348 quad= bs->quad; 02349 bake_set_shade_input(obi, vlr, shi, quad, 0, x, y, u, v); 02350 02351 if(bs->type==RE_BAKE_NORMALS && R.r.bake_normal_space==R_BAKE_SPACE_TANGENT) { 02352 shade_input_set_shade_texco(shi); 02353 VECCOPY(tvn, shi->nmapnorm); 02354 QUATCOPY(ttang, shi->nmaptang); 02355 } 02356 02357 /* if we are doing selected to active baking, find point on other face */ 02358 if(bs->actob) { 02359 Isect isec, minisec; 02360 float co[3], minco[3], dist, mindist=0.0f; 02361 int hit, sign, dir=1; 02362 02363 /* intersect with ray going forward and backward*/ 02364 hit= 0; 02365 memset(&minisec, 0, sizeof(minisec)); 02366 minco[0]= minco[1]= minco[2]= 0.0f; 02367 02368 VECCOPY(bs->dir, shi->vn); 02369 02370 for(sign=-1; sign<=1; sign+=2) { 02371 memset(&isec, 0, sizeof(isec)); 02372 isec.mode= RE_RAY_MIRROR; 02373 02374 isec.orig.ob = obi; 02375 isec.orig.face = vlr; 02376 isec.userdata= bs->actob; 02377 isec.check = RE_CHECK_VLR_BAKE; 02378 isec.skip = RE_SKIP_VLR_NEIGHBOUR; 02379 02380 if(bake_intersect_tree(R.raytree, &isec, shi->co, shi->vn, sign, co, &dist)) { 02381 if(!hit || len_v3v3(shi->co, co) < len_v3v3(shi->co, minco)) { 02382 minisec= isec; 02383 mindist= dist; 02384 VECCOPY(minco, co); 02385 hit= 1; 02386 dir = sign; 02387 } 02388 } 02389 } 02390 02391 if (bs->type==RE_BAKE_DISPLACEMENT) { 02392 if(hit) 02393 bake_displacement(handle, shi, (dir==-1)? mindist:-mindist, x, y); 02394 else 02395 bake_displacement(handle, shi, 0.0f, x, y); 02396 return; 02397 } 02398 02399 /* if hit, we shade from the new point, otherwise from point one starting face */ 02400 if(hit) { 02401 obi= (ObjectInstanceRen*)minisec.hit.ob; 02402 vlr= (VlakRen*)minisec.hit.face; 02403 quad= (minisec.isect == 2); 02404 VECCOPY(shi->co, minco); 02405 02406 u= -minisec.u; 02407 v= -minisec.v; 02408 bake_set_shade_input(obi, vlr, shi, quad, 1, x, y, u, v); 02409 } 02410 } 02411 02412 if(bs->type==RE_BAKE_NORMALS && R.r.bake_normal_space==R_BAKE_SPACE_TANGENT) 02413 bake_shade(handle, ob, shi, quad, x, y, u, v, tvn, ttang); 02414 else 02415 bake_shade(handle, ob, shi, quad, x, y, u, v, 0, 0); 02416 } 02417 02418 static int get_next_bake_face(BakeShade *bs) 02419 { 02420 ObjectRen *obr; 02421 VlakRen *vlr; 02422 MTFace *tface; 02423 static int v= 0, vdone= 0; 02424 static ObjectInstanceRen *obi= NULL; 02425 02426 if(bs==NULL) { 02427 vlr= NULL; 02428 v= vdone= 0; 02429 obi= R.instancetable.first; 02430 return 0; 02431 } 02432 02433 BLI_lock_thread(LOCK_CUSTOM1); 02434 02435 for(; obi; obi=obi->next, v=0) { 02436 obr= obi->obr; 02437 02438 for(; v<obr->totvlak; v++) { 02439 vlr= RE_findOrAddVlak(obr, v); 02440 02441 if((bs->actob && bs->actob == obr->ob) || (!bs->actob && (obr->ob->flag & SELECT))) { 02442 tface= RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0); 02443 02444 if(tface && tface->tpage) { 02445 Image *ima= tface->tpage; 02446 ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); 02447 const float vec_alpha[4]= {0.0f, 0.0f, 0.0f, 0.0f}; 02448 const float vec_solid[4]= {0.0f, 0.0f, 0.0f, 1.0f}; 02449 02450 if(ibuf==NULL) 02451 continue; 02452 02453 if(ibuf->rect==NULL && ibuf->rect_float==NULL) 02454 continue; 02455 02456 if(ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4)) 02457 continue; 02458 02459 /* find the image for the first time? */ 02460 if(ima->id.flag & LIB_DOIT) { 02461 ima->id.flag &= ~LIB_DOIT; 02462 02463 /* we either fill in float or char, this ensures things go fine */ 02464 if(ibuf->rect_float) 02465 imb_freerectImBuf(ibuf); 02466 /* clear image */ 02467 if(R.r.bake_flag & R_BAKE_CLEAR) 02468 IMB_rectfill(ibuf, (ibuf->depth == 32) ? vec_alpha : vec_solid); 02469 02470 /* might be read by UI to set active image for display */ 02471 R.bakebuf= ima; 02472 } 02473 02474 bs->obi= obi; 02475 bs->vlr= vlr; 02476 02477 bs->vdone++; /* only for error message if nothing was rendered */ 02478 v++; 02479 02480 BLI_unlock_thread(LOCK_CUSTOM1); 02481 return 1; 02482 } 02483 } 02484 } 02485 } 02486 02487 BLI_unlock_thread(LOCK_CUSTOM1); 02488 return 0; 02489 } 02490 02491 /* already have tested for tface and ima and zspan */ 02492 static void shade_tface(BakeShade *bs) 02493 { 02494 VlakRen *vlr= bs->vlr; 02495 ObjectInstanceRen *obi= bs->obi; 02496 ObjectRen *obr= obi->obr; 02497 MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0); 02498 Image *ima= tface->tpage; 02499 float vec[4][2]; 02500 int a, i1, i2, i3; 02501 02502 /* check valid zspan */ 02503 if(ima!=bs->ima) { 02504 bs->ima= ima; 02505 bs->ibuf= BKE_image_get_ibuf(ima, NULL); 02506 /* note, these calls only free/fill contents of zspan struct, not zspan itself */ 02507 zbuf_free_span(bs->zspan); 02508 zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y, R.clipcrop); 02509 } 02510 02511 bs->rectx= bs->ibuf->x; 02512 bs->recty= bs->ibuf->y; 02513 bs->rect= bs->ibuf->rect; 02514 bs->rect_float= bs->ibuf->rect_float; 02515 bs->quad= 0; 02516 02517 if (bs->usemask) { 02518 if (bs->ibuf->userdata==NULL) { 02519 BLI_lock_thread(LOCK_CUSTOM1); 02520 if (bs->ibuf->userdata==NULL) /* since the thread was locked, its possible another thread alloced the value */ 02521 bs->ibuf->userdata = (void *)MEM_callocN(sizeof(char)*bs->rectx*bs->recty, "BakeMask"); 02522 bs->rect_mask= (char *)bs->ibuf->userdata; 02523 BLI_unlock_thread(LOCK_CUSTOM1); 02524 } else { 02525 bs->rect_mask= (char *)bs->ibuf->userdata; 02526 } 02527 } 02528 02529 /* get pixel level vertex coordinates */ 02530 for(a=0; a<4; a++) { 02531 /* Note, workaround for pixel aligned UVs which are common and can screw up our intersection tests 02532 * where a pixel gets in between 2 faces or the middle of a quad, 02533 * camera aligned quads also have this problem but they are less common. 02534 * Add a small offset to the UVs, fixes bug #18685 - Campbell */ 02535 vec[a][0]= tface->uv[a][0]*(float)bs->rectx - (0.5f + 0.001); 02536 vec[a][1]= tface->uv[a][1]*(float)bs->recty - (0.5f + 0.002); 02537 } 02538 02539 /* UV indices have to be corrected for possible quad->tria splits */ 02540 i1= 0; i2= 1; i3= 2; 02541 vlr_set_uv_indices(vlr, &i1, &i2, &i3); 02542 bake_set_vlr_dxyco(bs, vec[i1], vec[i2], vec[i3]); 02543 zspan_scanconvert(bs->zspan, bs, vec[i1], vec[i2], vec[i3], do_bake_shade); 02544 02545 if(vlr->v4) { 02546 bs->quad= 1; 02547 bake_set_vlr_dxyco(bs, vec[0], vec[2], vec[3]); 02548 zspan_scanconvert(bs->zspan, bs, vec[0], vec[2], vec[3], do_bake_shade); 02549 } 02550 } 02551 02552 static void *do_bake_thread(void *bs_v) 02553 { 02554 BakeShade *bs= bs_v; 02555 02556 while(get_next_bake_face(bs)) { 02557 shade_tface(bs); 02558 02559 /* fast threadsafe break test */ 02560 if(R.test_break(R.tbh)) 02561 break; 02562 02563 /* access is not threadsafe but since its just true/false probably ok 02564 * only used for interactive baking */ 02565 if(bs->do_update) 02566 *bs->do_update= TRUE; 02567 } 02568 bs->ready= 1; 02569 02570 return NULL; 02571 } 02572 02573 void RE_bake_ibuf_filter(ImBuf *ibuf, char *mask, const int filter) 02574 { 02575 /* must check before filtering */ 02576 const short is_new_alpha= (ibuf->depth != 32) && BKE_alphatest_ibuf(ibuf); 02577 02578 /* Margin */ 02579 if(filter) { 02580 IMB_filter_extend(ibuf, mask, filter); 02581 } 02582 02583 /* if the bake results in new alpha then change the image setting */ 02584 if(is_new_alpha) { 02585 ibuf->depth= 32; 02586 } 02587 else { 02588 if(filter && ibuf->depth != 32) { 02589 /* clear alpha added by filtering */ 02590 IMB_rectfill_alpha(ibuf, 1.0f); 02591 } 02592 } 02593 } 02594 02595 /* using object selection tags, the faces with UV maps get baked */ 02596 /* render should have been setup */ 02597 /* returns 0 if nothing was handled */ 02598 int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_update, float *progress) 02599 { 02600 BakeShade *handles; 02601 ListBase threads; 02602 Image *ima; 02603 int a, vdone=0, usemask=0; 02604 02605 /* initialize render global */ 02606 R= *re; 02607 R.bakebuf= NULL; 02608 02609 /* initialize static vars */ 02610 get_next_bake_face(NULL); 02611 02612 /* do we need a mask? */ 02613 if (re->r.bake_filter) 02614 usemask = 1; 02615 02616 /* baker uses this flag to detect if image was initialized */ 02617 for(ima= G.main->image.first; ima; ima= ima->id.next) { 02618 ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); 02619 ima->id.flag |= LIB_DOIT; 02620 if(ibuf) { 02621 ibuf->userdata = NULL; /* use for masking if needed */ 02622 if(ibuf->rect_float) 02623 ibuf->profile = IB_PROFILE_LINEAR_RGB; 02624 } 02625 } 02626 02627 BLI_init_threads(&threads, do_bake_thread, re->r.threads); 02628 02629 handles= MEM_callocN(sizeof(BakeShade)*re->r.threads, "BakeShade"); 02630 02631 /* get the threads running */ 02632 for(a=0; a<re->r.threads; a++) { 02633 /* set defaults in handles */ 02634 handles[a].ssamp.shi[0].lay= re->lay; 02635 02636 if (type==RE_BAKE_SHADOW) { 02637 handles[a].ssamp.shi[0].passflag= SCE_PASS_SHADOW; 02638 } else { 02639 handles[a].ssamp.shi[0].passflag= SCE_PASS_COMBINED; 02640 } 02641 handles[a].ssamp.shi[0].combinedflag= ~(SCE_PASS_SPEC); 02642 handles[a].ssamp.shi[0].thread= a; 02643 handles[a].ssamp.tot= 1; 02644 02645 handles[a].type= type; 02646 handles[a].actob= actob; 02647 handles[a].zspan= MEM_callocN(sizeof(ZSpan), "zspan for bake"); 02648 02649 handles[a].usemask = usemask; 02650 02651 handles[a].do_update = do_update; /* use to tell the view to update */ 02652 02653 BLI_insert_thread(&threads, &handles[a]); 02654 } 02655 02656 /* wait for everything to be done */ 02657 a= 0; 02658 while(a!=re->r.threads) { 02659 PIL_sleep_ms(50); 02660 02661 /* calculate progress */ 02662 for(vdone=0, a=0; a<re->r.threads; a++) 02663 vdone+= handles[a].vdone; 02664 if (progress) 02665 *progress = (float)(vdone / (float)re->totvlak); 02666 02667 for(a=0; a<re->r.threads; a++) { 02668 if(handles[a].ready==0) 02669 break; 02670 } 02671 } 02672 02673 /* filter and refresh images */ 02674 for(ima= G.main->image.first; ima; ima= ima->id.next) { 02675 if((ima->id.flag & LIB_DOIT)==0) { 02676 ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); 02677 02678 if(!ibuf) 02679 continue; 02680 02681 RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, re->r.bake_filter); 02682 02683 ibuf->userflags |= IB_BITMAPDIRTY; 02684 if (ibuf->rect_float) IMB_rect_from_float(ibuf); 02685 } 02686 } 02687 02688 /* calculate return value */ 02689 for(a=0; a<re->r.threads; a++) { 02690 zbuf_free_span(handles[a].zspan); 02691 MEM_freeN(handles[a].zspan); 02692 } 02693 02694 MEM_freeN(handles); 02695 02696 BLI_end_threads(&threads); 02697 02698 return vdone; 02699 } 02700 02701 struct Image *RE_bake_shade_get_image(void) 02702 { 02703 return R.bakebuf; 02704 } 02705