|
Blender
V2.59
|
00001 /* 00002 * $Id: shadeoutput.c 37667 2011-06-20 15:17:02Z 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) 2006 Blender Foundation 00021 * All rights reserved. 00022 * 00023 * Contributors: Hos, Robert Wenzlaff. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <stdio.h> 00034 #include <float.h> 00035 #include <math.h> 00036 #include <string.h> 00037 00038 #include "BLI_math.h" 00039 #include "BLI_utildefines.h" 00040 00041 #include "BKE_colortools.h" 00042 #include "BKE_material.h" 00043 #include "BKE_texture.h" 00044 00045 00046 #include "DNA_group_types.h" 00047 #include "DNA_lamp_types.h" 00048 #include "DNA_material_types.h" 00049 00050 /* local include */ 00051 #include "occlusion.h" 00052 #include "renderpipeline.h" 00053 #include "render_types.h" 00054 #include "pixelblending.h" 00055 #include "rendercore.h" 00056 #include "shadbuf.h" 00057 #include "sss.h" 00058 #include "texture.h" 00059 00060 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00061 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ 00062 /* only to be used here in this file, it's for speed */ 00063 extern struct Render R; 00064 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00065 00066 ListBase *get_lights(ShadeInput *shi) 00067 { 00068 00069 if(R.r.scemode & R_PREVIEWBUTS) 00070 return &R.lights; 00071 if(shi->light_override) 00072 return &shi->light_override->gobject; 00073 if(shi->mat && shi->mat->group) 00074 return &shi->mat->group->gobject; 00075 00076 return &R.lights; 00077 } 00078 00079 #if 0 00080 static void fogcolor(float *colf, float *rco, float *view) 00081 { 00082 float alpha, stepsize, startdist, dist, hor[4], zen[3], vec[3], dview[3]; 00083 float div=0.0f, distfac; 00084 00085 hor[0]= R.wrld.horr; hor[1]= R.wrld.horg; hor[2]= R.wrld.horb; 00086 zen[0]= R.wrld.zenr; zen[1]= R.wrld.zeng; zen[2]= R.wrld.zenb; 00087 00088 VECCOPY(vec, rco); 00089 00090 /* we loop from cur coord to mist start in steps */ 00091 stepsize= 1.0f; 00092 00093 div= ABS(view[2]); 00094 dview[0]= view[0]/(stepsize*div); 00095 dview[1]= view[1]/(stepsize*div); 00096 dview[2]= -stepsize; 00097 00098 startdist= -rco[2] + BLI_frand(); 00099 for(dist= startdist; dist>R.wrld.miststa; dist-= stepsize) { 00100 00101 hor[0]= R.wrld.horr; hor[1]= R.wrld.horg; hor[2]= R.wrld.horb; 00102 alpha= 1.0f; 00103 do_sky_tex(vec, vec, NULL, hor, zen, &alpha); 00104 00105 distfac= (dist-R.wrld.miststa)/R.wrld.mistdist; 00106 00107 hor[3]= hor[0]*distfac*distfac; 00108 00109 /* premul! */ 00110 alpha= hor[3]; 00111 hor[0]= hor[0]*alpha; 00112 hor[1]= hor[1]*alpha; 00113 hor[2]= hor[2]*alpha; 00114 addAlphaOverFloat(colf, hor); 00115 00116 VECSUB(vec, vec, dview); 00117 } 00118 } 00119 #endif 00120 00121 /* zcor is distance, co the 3d coordinate in eye space, return alpha */ 00122 float mistfactor(float zcor, float *co) 00123 { 00124 float fac, hi; 00125 00126 fac= zcor - R.wrld.miststa; /* zcor is calculated per pixel */ 00127 00128 /* fac= -co[2]-R.wrld.miststa; */ 00129 00130 if(fac>0.0f) { 00131 if(fac< R.wrld.mistdist) { 00132 00133 fac= (fac/(R.wrld.mistdist)); 00134 00135 if(R.wrld.mistype==0) fac*= fac; 00136 else if(R.wrld.mistype==1); 00137 else fac= sqrt(fac); 00138 } 00139 else fac= 1.0f; 00140 } 00141 else fac= 0.0f; 00142 00143 /* height switched off mist */ 00144 if(R.wrld.misthi!=0.0f && fac!=0.0f) { 00145 /* at height misthi the mist is completely gone */ 00146 00147 hi= R.viewinv[0][2]*co[0]+R.viewinv[1][2]*co[1]+R.viewinv[2][2]*co[2]+R.viewinv[3][2]; 00148 00149 if(hi>R.wrld.misthi) fac= 0.0f; 00150 else if(hi>0.0f) { 00151 hi= (R.wrld.misthi-hi)/R.wrld.misthi; 00152 fac*= hi*hi; 00153 } 00154 } 00155 00156 return (1.0f-fac)* (1.0f-R.wrld.misi); 00157 } 00158 00159 static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens) 00160 { 00161 double a, b, c, disc, nray[3], npos[3]; 00162 double t0, t1 = 0.0f, t2= 0.0f, t3; 00163 float p1[3], p2[3], ladist, maxz = 0.0f, maxy = 0.0f, haint; 00164 int snijp, doclip=1, use_yco=0; 00165 int ok1=0, ok2=0; 00166 00167 *intens= 0.0f; 00168 haint= lar->haint; 00169 00170 if(R.r.mode & R_ORTHO) { 00171 /* camera pos (view vector) cannot be used... */ 00172 /* camera position (cox,coy,0) rotate around lamp */ 00173 p1[0]= shi->co[0]-lar->co[0]; 00174 p1[1]= shi->co[1]-lar->co[1]; 00175 p1[2]= -lar->co[2]; 00176 mul_m3_v3(lar->imat, p1); 00177 VECCOPY(npos, p1); // npos is double! 00178 00179 /* pre-scale */ 00180 npos[2]*= lar->sh_zfac; 00181 } 00182 else { 00183 VECCOPY(npos, lar->sh_invcampos); /* in initlamp calculated */ 00184 } 00185 00186 /* rotate view */ 00187 VECCOPY(nray, shi->view); 00188 mul_m3_v3_double(lar->imat, nray); 00189 00190 if(R.wrld.mode & WO_MIST) { 00191 /* patchy... */ 00192 haint *= mistfactor(-lar->co[2], lar->co); 00193 if(haint==0.0f) { 00194 return; 00195 } 00196 } 00197 00198 00199 /* rotate maxz */ 00200 if(shi->co[2]==0.0f) doclip= 0; /* for when halo at sky */ 00201 else { 00202 p1[0]= shi->co[0]-lar->co[0]; 00203 p1[1]= shi->co[1]-lar->co[1]; 00204 p1[2]= shi->co[2]-lar->co[2]; 00205 00206 maxz= lar->imat[0][2]*p1[0]+lar->imat[1][2]*p1[1]+lar->imat[2][2]*p1[2]; 00207 maxz*= lar->sh_zfac; 00208 maxy= lar->imat[0][1]*p1[0]+lar->imat[1][1]*p1[1]+lar->imat[2][1]*p1[2]; 00209 00210 if( fabs(nray[2]) < FLT_EPSILON ) use_yco= 1; 00211 } 00212 00213 /* scale z to make sure volume is normalized */ 00214 nray[2]*= lar->sh_zfac; 00215 /* nray does not need normalization */ 00216 00217 ladist= lar->sh_zfac*lar->dist; 00218 00219 /* solve */ 00220 a = nray[0] * nray[0] + nray[1] * nray[1] - nray[2]*nray[2]; 00221 b = nray[0] * npos[0] + nray[1] * npos[1] - nray[2]*npos[2]; 00222 c = npos[0] * npos[0] + npos[1] * npos[1] - npos[2]*npos[2]; 00223 00224 snijp= 0; 00225 if (fabs(a) < DBL_EPSILON) { 00226 /* 00227 * Only one intersection point... 00228 */ 00229 return; 00230 } 00231 else { 00232 disc = b*b - a*c; 00233 00234 if(disc==0.0) { 00235 t1=t2= (-b)/ a; 00236 snijp= 2; 00237 } 00238 else if (disc > 0.0) { 00239 disc = sqrt(disc); 00240 t1 = (-b + disc) / a; 00241 t2 = (-b - disc) / a; 00242 snijp= 2; 00243 } 00244 } 00245 if(snijp==2) { 00246 /* sort */ 00247 if(t1>t2) { 00248 a= t1; t1= t2; t2= a; 00249 } 00250 00251 /* z of intersection points with diabolo */ 00252 p1[2]= npos[2] + t1*nray[2]; 00253 p2[2]= npos[2] + t2*nray[2]; 00254 00255 /* evaluate both points */ 00256 if(p1[2]<=0.0f) ok1= 1; 00257 if(p2[2]<=0.0f && t1!=t2) ok2= 1; 00258 00259 /* at least 1 point with negative z */ 00260 if(ok1==0 && ok2==0) return; 00261 00262 /* intersction point with -ladist, the bottom of the cone */ 00263 if(use_yco==0) { 00264 t3= (-ladist-npos[2])/nray[2]; 00265 00266 /* de we have to replace one of the intersection points? */ 00267 if(ok1) { 00268 if(p1[2]<-ladist) t1= t3; 00269 } 00270 else { 00271 ok1= 1; 00272 t1= t3; 00273 } 00274 if(ok2) { 00275 if(p2[2]<-ladist) t2= t3; 00276 } 00277 else { 00278 ok2= 1; 00279 t2= t3; 00280 } 00281 } 00282 else if(ok1==0 || ok2==0) return; 00283 00284 /* at least 1 visible interesction point */ 00285 if(t1<0.0f && t2<0.0f) return; 00286 00287 if(t1<0.0f) t1= 0.0f; 00288 if(t2<0.0f) t2= 0.0f; 00289 00290 if(t1==t2) return; 00291 00292 /* sort again to be sure */ 00293 if(t1>t2) { 00294 a= t1; t1= t2; t2= a; 00295 } 00296 00297 /* calculate t0: is the maximum visible z (when halo is intersected by face) */ 00298 if(doclip) { 00299 if(use_yco==0) t0= (maxz-npos[2])/nray[2]; 00300 else t0= (maxy-npos[1])/nray[1]; 00301 00302 if(t0<t1) return; 00303 if(t0<t2) t2= t0; 00304 } 00305 00306 /* calc points */ 00307 p1[0]= npos[0] + t1*nray[0]; 00308 p1[1]= npos[1] + t1*nray[1]; 00309 p1[2]= npos[2] + t1*nray[2]; 00310 p2[0]= npos[0] + t2*nray[0]; 00311 p2[1]= npos[1] + t2*nray[1]; 00312 p2[2]= npos[2] + t2*nray[2]; 00313 00314 00315 /* now we have 2 points, make three lengths with it */ 00316 00317 a= sqrt(p1[0]*p1[0]+p1[1]*p1[1]+p1[2]*p1[2]); 00318 b= sqrt(p2[0]*p2[0]+p2[1]*p2[1]+p2[2]*p2[2]); 00319 c= len_v3v3(p1, p2); 00320 00321 a/= ladist; 00322 a= sqrt(a); 00323 b/= ladist; 00324 b= sqrt(b); 00325 c/= ladist; 00326 00327 *intens= c*( (1.0-a)+(1.0-b) ); 00328 00329 /* WATCH IT: do not clip a,b en c at 1.0, this gives nasty little overflows 00330 at the edges (especially with narrow halos) */ 00331 if(*intens<=0.0f) return; 00332 00333 /* soft area */ 00334 /* not needed because t0 has been used for p1/p2 as well */ 00335 /* if(doclip && t0<t2) { */ 00336 /* *intens *= (t0-t1)/(t2-t1); */ 00337 /* } */ 00338 00339 *intens *= haint; 00340 00341 if(lar->shb && lar->shb->shadhalostep) { 00342 *intens *= shadow_halo(lar, p1, p2); 00343 } 00344 00345 } 00346 } 00347 00348 void renderspothalo(ShadeInput *shi, float *col, float alpha) 00349 { 00350 ListBase *lights; 00351 GroupObject *go; 00352 LampRen *lar; 00353 float i; 00354 00355 if(alpha==0.0f) return; 00356 00357 lights= get_lights(shi); 00358 for(go=lights->first; go; go= go->next) { 00359 lar= go->lampren; 00360 if(lar==NULL) continue; 00361 00362 if(lar->type==LA_SPOT && (lar->mode & LA_HALO) && (lar->buftype != LA_SHADBUF_DEEP) && lar->haint>0) { 00363 00364 if(lar->mode & LA_LAYER) 00365 if(shi->vlr && (lar->lay & shi->obi->lay)==0) 00366 continue; 00367 if((lar->lay & shi->lay)==0) 00368 continue; 00369 00370 spothalo(lar, shi, &i); 00371 if(i>0.0f) { 00372 col[3]+= i*alpha; // all premul 00373 col[0]+= i*lar->r*alpha; 00374 col[1]+= i*lar->g*alpha; 00375 col[2]+= i*lar->b*alpha; 00376 } 00377 } 00378 } 00379 /* clip alpha, is needed for unified 'alpha threshold' (vanillaRenderPipe.c) */ 00380 if(col[3]>1.0f) col[3]= 1.0f; 00381 } 00382 00383 00384 00385 /* ---------------- shaders ----------------------- */ 00386 00387 static double Normalize_d(double *n) 00388 { 00389 double d; 00390 00391 d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2]; 00392 00393 if(d>0.00000000000000001) { 00394 d= sqrt(d); 00395 00396 n[0]/=d; 00397 n[1]/=d; 00398 n[2]/=d; 00399 } else { 00400 n[0]=n[1]=n[2]= 0.0; 00401 d= 0.0; 00402 } 00403 return d; 00404 } 00405 00406 /* mix of 'real' fresnel and allowing control. grad defines blending gradient */ 00407 float fresnel_fac(float *view, float *vn, float grad, float fac) 00408 { 00409 float t1, t2; 00410 00411 if(fac==0.0f) return 1.0f; 00412 00413 t1= (view[0]*vn[0] + view[1]*vn[1] + view[2]*vn[2]); 00414 if(t1>0.0f) t2= 1.0f+t1; 00415 else t2= 1.0f-t1; 00416 00417 t2= grad + (1.0f-grad)*pow(t2, fac); 00418 00419 if(t2<0.0f) return 0.0f; 00420 else if(t2>1.0f) return 1.0f; 00421 return t2; 00422 } 00423 00424 static double saacos_d(double fac) 00425 { 00426 if(fac<= -1.0f) return M_PI; 00427 else if(fac>=1.0f) return 0.0; 00428 else return acos(fac); 00429 } 00430 00431 /* Stoke's form factor. Need doubles here for extreme small area sizes */ 00432 static float area_lamp_energy(float (*area)[3], float *co, float *vn) 00433 { 00434 double fac; 00435 double vec[4][3]; /* vectors of rendered co to vertices lamp */ 00436 double cross[4][3]; /* cross products of this */ 00437 double rad[4]; /* angles between vecs */ 00438 00439 VECSUB(vec[0], co, area[0]); 00440 VECSUB(vec[1], co, area[1]); 00441 VECSUB(vec[2], co, area[2]); 00442 VECSUB(vec[3], co, area[3]); 00443 00444 Normalize_d(vec[0]); 00445 Normalize_d(vec[1]); 00446 Normalize_d(vec[2]); 00447 Normalize_d(vec[3]); 00448 00449 /* cross product */ 00450 CROSS(cross[0], vec[0], vec[1]); 00451 CROSS(cross[1], vec[1], vec[2]); 00452 CROSS(cross[2], vec[2], vec[3]); 00453 CROSS(cross[3], vec[3], vec[0]); 00454 00455 Normalize_d(cross[0]); 00456 Normalize_d(cross[1]); 00457 Normalize_d(cross[2]); 00458 Normalize_d(cross[3]); 00459 00460 /* angles */ 00461 rad[0]= vec[0][0]*vec[1][0]+ vec[0][1]*vec[1][1]+ vec[0][2]*vec[1][2]; 00462 rad[1]= vec[1][0]*vec[2][0]+ vec[1][1]*vec[2][1]+ vec[1][2]*vec[2][2]; 00463 rad[2]= vec[2][0]*vec[3][0]+ vec[2][1]*vec[3][1]+ vec[2][2]*vec[3][2]; 00464 rad[3]= vec[3][0]*vec[0][0]+ vec[3][1]*vec[0][1]+ vec[3][2]*vec[0][2]; 00465 00466 rad[0]= saacos_d(rad[0]); 00467 rad[1]= saacos_d(rad[1]); 00468 rad[2]= saacos_d(rad[2]); 00469 rad[3]= saacos_d(rad[3]); 00470 00471 /* Stoke formula */ 00472 fac= rad[0]*(vn[0]*cross[0][0]+ vn[1]*cross[0][1]+ vn[2]*cross[0][2]); 00473 fac+= rad[1]*(vn[0]*cross[1][0]+ vn[1]*cross[1][1]+ vn[2]*cross[1][2]); 00474 fac+= rad[2]*(vn[0]*cross[2][0]+ vn[1]*cross[2][1]+ vn[2]*cross[2][2]); 00475 fac+= rad[3]*(vn[0]*cross[3][0]+ vn[1]*cross[3][1]+ vn[2]*cross[3][2]); 00476 00477 if(fac<=0.0) return 0.0; 00478 return fac; 00479 } 00480 00481 static float area_lamp_energy_multisample(LampRen *lar, float *co, float *vn) 00482 { 00483 /* corner vectors are moved around according lamp jitter */ 00484 float *jitlamp= lar->jitter, vec[3]; 00485 float area[4][3], intens= 0.0f; 00486 int a= lar->ray_totsamp; 00487 00488 /* test if co is behind lamp */ 00489 VECSUB(vec, co, lar->co); 00490 if(INPR(vec, lar->vec) < 0.0f) 00491 return 0.0f; 00492 00493 while(a--) { 00494 vec[0]= jitlamp[0]; 00495 vec[1]= jitlamp[1]; 00496 vec[2]= 0.0f; 00497 mul_m3_v3(lar->mat, vec); 00498 00499 VECADD(area[0], lar->area[0], vec); 00500 VECADD(area[1], lar->area[1], vec); 00501 VECADD(area[2], lar->area[2], vec); 00502 VECADD(area[3], lar->area[3], vec); 00503 00504 intens+= area_lamp_energy(area, co, vn); 00505 00506 jitlamp+= 2; 00507 } 00508 intens /= (float)lar->ray_totsamp; 00509 00510 return pow(intens*lar->areasize, lar->k); // corrected for buttons size and lar->dist^2 00511 } 00512 00513 static float spec(float inp, int hard) 00514 { 00515 float b1; 00516 00517 if(inp>=1.0f) return 1.0f; 00518 else if (inp<=0.0f) return 0.0f; 00519 00520 b1= inp*inp; 00521 /* avoid FPE */ 00522 if(b1<0.01f) b1= 0.01f; 00523 00524 if((hard & 1)==0) inp= 1.0f; 00525 if(hard & 2) inp*= b1; 00526 b1*= b1; 00527 if(hard & 4) inp*= b1; 00528 b1*= b1; 00529 if(hard & 8) inp*= b1; 00530 b1*= b1; 00531 if(hard & 16) inp*= b1; 00532 b1*= b1; 00533 00534 /* avoid FPE */ 00535 if(b1<0.001f) b1= 0.0f; 00536 00537 if(hard & 32) inp*= b1; 00538 b1*= b1; 00539 if(hard & 64) inp*=b1; 00540 b1*= b1; 00541 if(hard & 128) inp*=b1; 00542 00543 if(b1<0.001f) b1= 0.0f; 00544 00545 if(hard & 256) { 00546 b1*= b1; 00547 inp*=b1; 00548 } 00549 00550 return inp; 00551 } 00552 00553 static float Phong_Spec( float *n, float *l, float *v, int hard, int tangent ) 00554 { 00555 float h[3]; 00556 float rslt; 00557 00558 h[0] = l[0] + v[0]; 00559 h[1] = l[1] + v[1]; 00560 h[2] = l[2] + v[2]; 00561 normalize_v3(h); 00562 00563 rslt = h[0]*n[0] + h[1]*n[1] + h[2]*n[2]; 00564 if(tangent) rslt= sasqrt(1.0f - rslt*rslt); 00565 00566 if( rslt > 0.0f ) rslt= spec(rslt, hard); 00567 else rslt = 0.0f; 00568 00569 return rslt; 00570 } 00571 00572 00573 /* reduced cook torrance spec (for off-specular peak) */ 00574 static float CookTorr_Spec(float *n, float *l, float *v, int hard, int tangent) 00575 { 00576 float i, nh, nv, h[3]; 00577 00578 h[0]= v[0]+l[0]; 00579 h[1]= v[1]+l[1]; 00580 h[2]= v[2]+l[2]; 00581 normalize_v3(h); 00582 00583 nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; 00584 if(tangent) nh= sasqrt(1.0f - nh*nh); 00585 else if(nh<0.0f) return 0.0f; 00586 00587 nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; 00588 if(tangent) nv= sasqrt(1.0f - nv*nv); 00589 else if(nv<0.0f) nv= 0.0f; 00590 00591 i= spec(nh, hard); 00592 00593 i= i/(0.1+nv); 00594 return i; 00595 } 00596 00597 /* Blinn spec */ 00598 static float Blinn_Spec(float *n, float *l, float *v, float refrac, float spec_power, int tangent) 00599 { 00600 float i, nh, nv, nl, vh, h[3]; 00601 float a, b, c, g=0.0f, p, f, ang; 00602 00603 if(refrac < 1.0f) return 0.0f; 00604 if(spec_power == 0.0f) return 0.0f; 00605 00606 /* conversion from 'hardness' (1-255) to 'spec_power' (50 maps at 0.1) */ 00607 if(spec_power<100.0f) 00608 spec_power= sqrt(1.0f/spec_power); 00609 else spec_power= 10.0f/spec_power; 00610 00611 h[0]= v[0]+l[0]; 00612 h[1]= v[1]+l[1]; 00613 h[2]= v[2]+l[2]; 00614 normalize_v3(h); 00615 00616 nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */ 00617 if(tangent) nh= sasqrt(1.0f - nh*nh); 00618 else if(nh<0.0f) return 0.0f; 00619 00620 nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */ 00621 if(tangent) nv= sasqrt(1.0f - nv*nv); 00622 if(nv<=0.01f) nv= 0.01f; /* hrms... */ 00623 00624 nl= n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */ 00625 if(tangent) nl= sasqrt(1.0f - nl*nl); 00626 if(nl<=0.01f) { 00627 return 0.0f; 00628 } 00629 00630 vh= v[0]*h[0]+v[1]*h[1]+v[2]*h[2]; /* Dot product between view vector and half-way vector */ 00631 if(vh<=0.0f) vh= 0.01f; 00632 00633 a = 1.0f; 00634 b = (2.0f*nh*nv)/vh; 00635 c = (2.0f*nh*nl)/vh; 00636 00637 if( a < b && a < c ) g = a; 00638 else if( b < a && b < c ) g = b; 00639 else if( c < a && c < b ) g = c; 00640 00641 p = sqrt( (double)((refrac * refrac)+(vh*vh)-1.0f) ); 00642 f = (((p-vh)*(p-vh))/((p+vh)*(p+vh)))*(1+((((vh*(p+vh))-1.0f)*((vh*(p+vh))-1.0f))/(((vh*(p-vh))+1.0f)*((vh*(p-vh))+1.0f)))); 00643 ang = saacos(nh); 00644 00645 i= f * g * exp((double)(-(ang*ang) / (2.0f*spec_power*spec_power))); 00646 if(i<0.0f) i= 0.0f; 00647 00648 return i; 00649 } 00650 00651 /* cartoon render spec */ 00652 static float Toon_Spec( float *n, float *l, float *v, float size, float smooth, int tangent) 00653 { 00654 float h[3]; 00655 float ang; 00656 float rslt; 00657 00658 h[0] = l[0] + v[0]; 00659 h[1] = l[1] + v[1]; 00660 h[2] = l[2] + v[2]; 00661 normalize_v3(h); 00662 00663 rslt = h[0]*n[0] + h[1]*n[1] + h[2]*n[2]; 00664 if(tangent) rslt = sasqrt(1.0f - rslt*rslt); 00665 00666 ang = saacos( rslt ); 00667 00668 if( ang < size ) rslt = 1.0f; 00669 else if( ang >= (size + smooth) || smooth == 0.0f ) rslt = 0.0f; 00670 else rslt = 1.0f - ((ang - size) / smooth); 00671 00672 return rslt; 00673 } 00674 00675 /* Ward isotropic gaussian spec */ 00676 static float WardIso_Spec( float *n, float *l, float *v, float rms, int tangent) 00677 { 00678 float i, nh, nv, nl, h[3], angle, alpha; 00679 00680 00681 /* half-way vector */ 00682 h[0] = l[0] + v[0]; 00683 h[1] = l[1] + v[1]; 00684 h[2] = l[2] + v[2]; 00685 normalize_v3(h); 00686 00687 nh = n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */ 00688 if(tangent) nh = sasqrt(1.0f - nh*nh); 00689 if(nh<=0.0f) nh = 0.001f; 00690 00691 nv = n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */ 00692 if(tangent) nv = sasqrt(1.0f - nv*nv); 00693 if(nv<=0.0f) nv = 0.001f; 00694 00695 nl = n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */ 00696 if(tangent) nl = sasqrt(1.0f - nl*nl); 00697 if(nl<=0.0f) nl = 0.001f; 00698 00699 angle = tan(saacos(nh)); 00700 alpha = MAX2(rms, 0.001f); 00701 00702 i= nl * (1.0f/(4.0f*M_PI*alpha*alpha)) * (exp( -(angle*angle)/(alpha*alpha))/(sqrt(nv*nl))); 00703 00704 return i; 00705 } 00706 00707 /* cartoon render diffuse */ 00708 static float Toon_Diff( float *n, float *l, float *UNUSED(v), float size, float smooth ) 00709 { 00710 float rslt, ang; 00711 00712 rslt = n[0]*l[0] + n[1]*l[1] + n[2]*l[2]; 00713 00714 ang = saacos( (double)(rslt) ); 00715 00716 if( ang < size ) rslt = 1.0f; 00717 else if( ang >= (size + smooth) || smooth == 0.0f ) rslt = 0.0f; 00718 else rslt = 1.0f - ((ang - size) / smooth); 00719 00720 return rslt; 00721 } 00722 00723 /* Oren Nayar diffuse */ 00724 00725 /* 'nl' is either dot product, or return value of area light */ 00726 /* in latter case, only last multiplication uses 'nl' */ 00727 static float OrenNayar_Diff(float nl, float *n, float *l, float *v, float rough ) 00728 { 00729 float i/*, nh*/, nv, vh, realnl, h[3]; 00730 float a, b, t, A, B; 00731 float Lit_A, View_A, Lit_B[3], View_B[3]; 00732 00733 h[0]= v[0]+l[0]; 00734 h[1]= v[1]+l[1]; 00735 h[2]= v[2]+l[2]; 00736 normalize_v3(h); 00737 00738 /* nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; */ /* Dot product between surface normal and half-way vector */ 00739 /* if(nh<0.0f) nh = 0.0f; */ 00740 00741 nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */ 00742 if(nv<=0.0f) nv= 0.0f; 00743 00744 realnl= n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */ 00745 if(realnl<=0.0f) return 0.0f; 00746 if(nl<0.0f) return 0.0f; /* value from area light */ 00747 00748 vh= v[0]*h[0]+v[1]*h[1]+v[2]*h[2]; /* Dot product between view vector and halfway vector */ 00749 if(vh<=0.0f) vh= 0.0f; 00750 00751 Lit_A = saacos(realnl); 00752 View_A = saacos( nv ); 00753 00754 Lit_B[0] = l[0] - (realnl * n[0]); 00755 Lit_B[1] = l[1] - (realnl * n[1]); 00756 Lit_B[2] = l[2] - (realnl * n[2]); 00757 normalize_v3( Lit_B ); 00758 00759 View_B[0] = v[0] - (nv * n[0]); 00760 View_B[1] = v[1] - (nv * n[1]); 00761 View_B[2] = v[2] - (nv * n[2]); 00762 normalize_v3( View_B ); 00763 00764 t = Lit_B[0]*View_B[0] + Lit_B[1]*View_B[1] + Lit_B[2]*View_B[2]; 00765 if( t < 0 ) t = 0; 00766 00767 if( Lit_A > View_A ) { 00768 a = Lit_A; 00769 b = View_A; 00770 } 00771 else { 00772 a = View_A; 00773 b = Lit_A; 00774 } 00775 00776 A = 1.0f - (0.5f * ((rough * rough) / ((rough * rough) + 0.33f))); 00777 B = 0.45f * ((rough * rough) / ((rough * rough) + 0.09f)); 00778 00779 b*= 0.95f; /* prevent tangens from shooting to inf, 'nl' can be not a dot product here. */ 00780 /* overflow only happens with extreme size area light, and higher roughness */ 00781 i = nl * ( A + ( B * t * sin(a) * tan(b) ) ); 00782 00783 return i; 00784 } 00785 00786 /* Minnaert diffuse */ 00787 static float Minnaert_Diff(float nl, float *n, float *v, float darkness) 00788 { 00789 00790 float i, nv; 00791 00792 /* nl = dot product between surface normal and light vector */ 00793 if (nl <= 0.0f) 00794 return 0.0f; 00795 00796 /* nv = dot product between surface normal and view vector */ 00797 nv = n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; 00798 if (nv < 0.0f) 00799 nv = 0.0f; 00800 00801 if (darkness <= 1.0f) 00802 i = nl * pow(MAX2(nv*nl, 0.1f), (darkness - 1.0f) ); /*The Real model*/ 00803 else 00804 i = nl * pow( (1.001f - nv), (darkness - 1.0f) ); /*Nvidia model*/ 00805 00806 return i; 00807 } 00808 00809 static float Fresnel_Diff(float *vn, float *lv, float *UNUSED(view), float fac_i, float fac) 00810 { 00811 return fresnel_fac(lv, vn, fac_i, fac); 00812 } 00813 00814 /* --------------------------------------------- */ 00815 /* also called from texture.c */ 00816 void calc_R_ref(ShadeInput *shi) 00817 { 00818 float i; 00819 00820 /* shi->vn dot shi->view */ 00821 i= -2*(shi->vn[0]*shi->view[0]+shi->vn[1]*shi->view[1]+shi->vn[2]*shi->view[2]); 00822 00823 shi->ref[0]= (shi->view[0]+i*shi->vn[0]); 00824 shi->ref[1]= (shi->view[1]+i*shi->vn[1]); 00825 shi->ref[2]= (shi->view[2]+i*shi->vn[2]); 00826 if(shi->osatex) { 00827 if(shi->vlr->flag & R_SMOOTH) { 00828 i= -2*( (shi->vn[0]+shi->dxno[0])*(shi->view[0]+shi->dxview) + 00829 (shi->vn[1]+shi->dxno[1])*shi->view[1]+ (shi->vn[2]+shi->dxno[2])*shi->view[2] ); 00830 00831 shi->dxref[0]= shi->ref[0]- ( shi->view[0]+shi->dxview+i*(shi->vn[0]+shi->dxno[0])); 00832 shi->dxref[1]= shi->ref[1]- (shi->view[1]+ i*(shi->vn[1]+shi->dxno[1])); 00833 shi->dxref[2]= shi->ref[2]- (shi->view[2]+ i*(shi->vn[2]+shi->dxno[2])); 00834 00835 i= -2*( (shi->vn[0]+shi->dyno[0])*shi->view[0]+ 00836 (shi->vn[1]+shi->dyno[1])*(shi->view[1]+shi->dyview)+ (shi->vn[2]+shi->dyno[2])*shi->view[2] ); 00837 00838 shi->dyref[0]= shi->ref[0]- (shi->view[0]+ i*(shi->vn[0]+shi->dyno[0])); 00839 shi->dyref[1]= shi->ref[1]- (shi->view[1]+shi->dyview+i*(shi->vn[1]+shi->dyno[1])); 00840 shi->dyref[2]= shi->ref[2]- (shi->view[2]+ i*(shi->vn[2]+shi->dyno[2])); 00841 00842 } 00843 else { 00844 00845 i= -2*( shi->vn[0]*(shi->view[0]+shi->dxview) + 00846 shi->vn[1]*shi->view[1]+ shi->vn[2]*shi->view[2] ); 00847 00848 shi->dxref[0]= shi->ref[0]- (shi->view[0]+shi->dxview+i*shi->vn[0]); 00849 shi->dxref[1]= shi->ref[1]- (shi->view[1]+ i*shi->vn[1]); 00850 shi->dxref[2]= shi->ref[2]- (shi->view[2]+ i*shi->vn[2]); 00851 00852 i= -2*( shi->vn[0]*shi->view[0]+ 00853 shi->vn[1]*(shi->view[1]+shi->dyview)+ shi->vn[2]*shi->view[2] ); 00854 00855 shi->dyref[0]= shi->ref[0]- (shi->view[0]+ i*shi->vn[0]); 00856 shi->dyref[1]= shi->ref[1]- (shi->view[1]+shi->dyview+i*shi->vn[1]); 00857 shi->dyref[2]= shi->ref[2]- (shi->view[2]+ i*shi->vn[2]); 00858 } 00859 } 00860 00861 } 00862 00863 /* called from ray.c */ 00864 void shade_color(ShadeInput *shi, ShadeResult *shr) 00865 { 00866 Material *ma= shi->mat; 00867 00868 if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) { 00869 shi->r= shi->vcol[0]; 00870 shi->g= shi->vcol[1]; 00871 shi->b= shi->vcol[2]; 00872 if(ma->mode & (MA_FACETEXTURE_ALPHA)) 00873 shi->alpha= shi->vcol[3]; 00874 } 00875 00876 if(ma->texco) 00877 do_material_tex(shi); 00878 00879 if(ma->fresnel_tra!=0.0f) 00880 shi->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra); 00881 00882 if (!(shi->mode & MA_TRANSP)) shi->alpha= 1.0f; 00883 00884 shr->diff[0]= shi->r; 00885 shr->diff[1]= shi->g; 00886 shr->diff[2]= shi->b; 00887 shr->alpha= shi->alpha; 00888 } 00889 00890 /* ramp for at end of shade */ 00891 static void ramp_diffuse_result(float *diff, ShadeInput *shi) 00892 { 00893 Material *ma= shi->mat; 00894 float col[4], fac=0; 00895 00896 if(ma->ramp_col) { 00897 if(ma->rampin_col==MA_RAMP_IN_RESULT) { 00898 00899 fac= 0.3*diff[0] + 0.58*diff[1] + 0.12*diff[2]; 00900 do_colorband(ma->ramp_col, fac, col); 00901 00902 /* blending method */ 00903 fac= col[3]*ma->rampfac_col; 00904 00905 ramp_blend(ma->rampblend_col, diff, diff+1, diff+2, fac, col); 00906 } 00907 } 00908 } 00909 00910 /* r,g,b denote energy, ramp is used with different values to make new material color */ 00911 static void add_to_diffuse(float *diff, ShadeInput *shi, float is, float r, float g, float b) 00912 { 00913 Material *ma= shi->mat; 00914 float col[4], colt[3], fac=0; 00915 00916 if(ma->ramp_col && (ma->mode & MA_RAMP_COL)) { 00917 00918 /* MA_RAMP_IN_RESULT is exceptional */ 00919 if(ma->rampin_col==MA_RAMP_IN_RESULT) { 00920 // normal add 00921 diff[0] += r * shi->r; 00922 diff[1] += g * shi->g; 00923 diff[2] += b * shi->b; 00924 } 00925 else { 00926 /* input */ 00927 switch(ma->rampin_col) { 00928 case MA_RAMP_IN_ENERGY: 00929 fac= 0.3*r + 0.58*g + 0.12*b; 00930 break; 00931 case MA_RAMP_IN_SHADER: 00932 fac= is; 00933 break; 00934 case MA_RAMP_IN_NOR: 00935 fac= shi->view[0]*shi->vn[0] + shi->view[1]*shi->vn[1] + shi->view[2]*shi->vn[2]; 00936 break; 00937 } 00938 00939 do_colorband(ma->ramp_col, fac, col); 00940 00941 /* blending method */ 00942 fac= col[3]*ma->rampfac_col; 00943 colt[0]= shi->r; 00944 colt[1]= shi->g; 00945 colt[2]= shi->b; 00946 00947 ramp_blend(ma->rampblend_col, colt, colt+1, colt+2, fac, col); 00948 00949 /* output to */ 00950 diff[0] += r * colt[0]; 00951 diff[1] += g * colt[1]; 00952 diff[2] += b * colt[2]; 00953 } 00954 } 00955 else { 00956 diff[0] += r * shi->r; 00957 diff[1] += g * shi->g; 00958 diff[2] += b * shi->b; 00959 } 00960 } 00961 00962 static void ramp_spec_result(float *specr, float *specg, float *specb, ShadeInput *shi) 00963 { 00964 Material *ma= shi->mat; 00965 float col[4]; 00966 float fac; 00967 00968 if(ma->ramp_spec && (ma->rampin_spec==MA_RAMP_IN_RESULT)) { 00969 fac= 0.3*(*specr) + 0.58*(*specg) + 0.12*(*specb); 00970 do_colorband(ma->ramp_spec, fac, col); 00971 00972 /* blending method */ 00973 fac= col[3]*ma->rampfac_spec; 00974 00975 ramp_blend(ma->rampblend_spec, specr, specg, specb, fac, col); 00976 00977 } 00978 } 00979 00980 /* is = dot product shade, t = spec energy */ 00981 static void do_specular_ramp(ShadeInput *shi, float is, float t, float *spec) 00982 { 00983 Material *ma= shi->mat; 00984 float col[4]; 00985 float fac=0.0f; 00986 00987 spec[0]= shi->specr; 00988 spec[1]= shi->specg; 00989 spec[2]= shi->specb; 00990 00991 /* MA_RAMP_IN_RESULT is exception */ 00992 if(ma->ramp_spec && (ma->rampin_spec!=MA_RAMP_IN_RESULT)) { 00993 00994 /* input */ 00995 switch(ma->rampin_spec) { 00996 case MA_RAMP_IN_ENERGY: 00997 fac= t; 00998 break; 00999 case MA_RAMP_IN_SHADER: 01000 fac= is; 01001 break; 01002 case MA_RAMP_IN_NOR: 01003 fac= shi->view[0]*shi->vn[0] + shi->view[1]*shi->vn[1] + shi->view[2]*shi->vn[2]; 01004 break; 01005 } 01006 01007 do_colorband(ma->ramp_spec, fac, col); 01008 01009 /* blending method */ 01010 fac= col[3]*ma->rampfac_spec; 01011 01012 ramp_blend(ma->rampblend_spec, spec, spec+1, spec+2, fac, col); 01013 } 01014 } 01015 01016 /* pure AO, check for raytrace and world should have been done */ 01017 /* preprocess, textures were not done, don't use shi->amb for that reason */ 01018 void ambient_occlusion(ShadeInput *shi) 01019 { 01020 if((R.wrld.ao_gather_method == WO_AOGATHER_APPROX) && shi->mat->amb!=0.0f) 01021 sample_occ(&R, shi); 01022 else if((R.r.mode & R_RAYTRACE) && shi->mat->amb!=0.0f) 01023 ray_ao(shi, shi->ao, shi->env); 01024 else 01025 shi->ao[0]= shi->ao[1]= shi->ao[2]= 1.0f; 01026 } 01027 01028 01029 /* wrld mode was checked for */ 01030 static void ambient_occlusion_apply(ShadeInput *shi, ShadeResult *shr) 01031 { 01032 float f= R.wrld.aoenergy; 01033 float tmp[3], tmpspec[3]; 01034 01035 if(!((R.r.mode & R_RAYTRACE) || R.wrld.ao_gather_method == WO_AOGATHER_APPROX)) 01036 return; 01037 if(f == 0.0f) 01038 return; 01039 01040 if(R.wrld.aomix==WO_AOADD) { 01041 shr->combined[0] += shi->ao[0]*shi->r*shi->refl*f; 01042 shr->combined[1] += shi->ao[1]*shi->g*shi->refl*f; 01043 shr->combined[2] += shi->ao[2]*shi->b*shi->refl*f; 01044 } 01045 else if(R.wrld.aomix==WO_AOMUL) { 01046 mul_v3_v3v3(tmp, shr->combined, shi->ao); 01047 mul_v3_v3v3(tmpspec, shr->spec, shi->ao); 01048 01049 if(f == 1.0f) { 01050 copy_v3_v3(shr->combined, tmp); 01051 copy_v3_v3(shr->spec, tmpspec); 01052 } 01053 else { 01054 interp_v3_v3v3(shr->combined, shr->combined, tmp, f); 01055 interp_v3_v3v3(shr->spec, shr->spec, tmpspec, f); 01056 } 01057 } 01058 } 01059 01060 void environment_lighting_apply(ShadeInput *shi, ShadeResult *shr) 01061 { 01062 float f= R.wrld.ao_env_energy*shi->amb; 01063 01064 if(!((R.r.mode & R_RAYTRACE) || R.wrld.ao_gather_method == WO_AOGATHER_APPROX)) 01065 return; 01066 if(f == 0.0f) 01067 return; 01068 01069 shr->combined[0] += shi->env[0]*shi->r*shi->refl*f; 01070 shr->combined[1] += shi->env[1]*shi->g*shi->refl*f; 01071 shr->combined[2] += shi->env[2]*shi->b*shi->refl*f; 01072 } 01073 01074 static void indirect_lighting_apply(ShadeInput *shi, ShadeResult *shr) 01075 { 01076 float f= R.wrld.ao_indirect_energy; 01077 01078 if(!((R.r.mode & R_RAYTRACE) || R.wrld.ao_gather_method == WO_AOGATHER_APPROX)) 01079 return; 01080 if(f == 0.0f) 01081 return; 01082 01083 shr->combined[0] += shi->indirect[0]*shi->r*shi->refl*f; 01084 shr->combined[1] += shi->indirect[1]*shi->g*shi->refl*f; 01085 shr->combined[2] += shi->indirect[2]*shi->b*shi->refl*f; 01086 } 01087 01088 /* result written in shadfac */ 01089 void lamp_get_shadow(LampRen *lar, ShadeInput *shi, float inp, float *shadfac, int do_real) 01090 { 01091 LampShadowSubSample *lss= &(lar->shadsamp[shi->thread].s[shi->sample]); 01092 01093 if(do_real || lss->samplenr!=shi->samplenr) { 01094 01095 shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 1.0f; 01096 01097 if(lar->shb) { 01098 if(lar->buftype==LA_SHADBUF_IRREGULAR) 01099 shadfac[3]= ISB_getshadow(shi, lar->shb); 01100 else 01101 shadfac[3] = testshadowbuf(&R, lar->shb, shi->co, shi->dxco, shi->dyco, inp, shi->mat->lbias); 01102 } 01103 else if(lar->mode & LA_SHAD_RAY) { 01104 ray_shadow(shi, lar, shadfac); 01105 } 01106 01107 if(shi->depth==0) { 01108 QUATCOPY(lss->shadfac, shadfac); 01109 lss->samplenr= shi->samplenr; 01110 } 01111 } 01112 else { 01113 QUATCOPY(shadfac, lss->shadfac); 01114 } 01115 } 01116 01117 /* lampdistance and spot angle, writes in lv and dist */ 01118 float lamp_get_visibility(LampRen *lar, float *co, float *lv, float *dist) 01119 { 01120 if(lar->type==LA_SUN || lar->type==LA_HEMI) { 01121 *dist= 1.0f; 01122 VECCOPY(lv, lar->vec); 01123 return 1.0f; 01124 } 01125 else { 01126 float visifac= 1.0f, t; 01127 01128 VECSUB(lv, co, lar->co); 01129 *dist= sqrt( INPR(lv, lv)); 01130 t= 1.0f/dist[0]; 01131 VECMUL(lv, t); 01132 01133 /* area type has no quad or sphere option */ 01134 if(lar->type==LA_AREA) { 01135 /* area is single sided */ 01136 //if(INPR(lv, lar->vec) > 0.0f) 01137 // visifac= 1.0f; 01138 //else 01139 // visifac= 0.0f; 01140 } 01141 else { 01142 switch(lar->falloff_type) 01143 { 01144 case LA_FALLOFF_CONSTANT: 01145 visifac = 1.0f; 01146 break; 01147 case LA_FALLOFF_INVLINEAR: 01148 visifac = lar->dist/(lar->dist + dist[0]); 01149 break; 01150 case LA_FALLOFF_INVSQUARE: 01151 /* NOTE: This seems to be a hack since commit r12045 says this 01152 * option is similar to old Quad, but with slight changes. 01153 * Correct inv square would be (which would be old Quad): 01154 * visifac = lar->distkw / (lar->distkw + dist[0]*dist[0]); 01155 */ 01156 visifac = lar->dist / (lar->dist + dist[0]*dist[0]); 01157 break; 01158 case LA_FALLOFF_SLIDERS: 01159 if(lar->ld1>0.0f) 01160 visifac= lar->dist/(lar->dist+lar->ld1*dist[0]); 01161 if(lar->ld2>0.0f) 01162 visifac*= lar->distkw/(lar->distkw+lar->ld2*dist[0]*dist[0]); 01163 break; 01164 case LA_FALLOFF_CURVE: 01165 visifac = curvemapping_evaluateF(lar->curfalloff, 0, dist[0]/lar->dist); 01166 break; 01167 } 01168 01169 if(lar->mode & LA_SPHERE) { 01170 float t= lar->dist - dist[0]; 01171 if(t<=0.0f) 01172 visifac= 0.0f; 01173 else 01174 visifac*= t/lar->dist; 01175 } 01176 01177 if(visifac > 0.0f) { 01178 if(lar->type==LA_SPOT) { 01179 float inpr; 01180 01181 if(lar->mode & LA_SQUARE) { 01182 if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0f) { 01183 float lvrot[3], x; 01184 01185 /* rotate view to lampspace */ 01186 VECCOPY(lvrot, lv); 01187 mul_m3_v3(lar->imat, lvrot); 01188 01189 x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2])); 01190 /* 1.0f/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */ 01191 01192 inpr= 1.0f/(sqrt(1.0f+x*x)); 01193 } 01194 else inpr= 0.0f; 01195 } 01196 else { 01197 inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]; 01198 } 01199 01200 t= lar->spotsi; 01201 if(inpr<=t) 01202 visifac= 0.0f; 01203 else { 01204 t= inpr-t; 01205 if(t<lar->spotbl && lar->spotbl!=0.0f) { 01206 /* soft area */ 01207 float i= t/lar->spotbl; 01208 t= i*i; 01209 inpr*= (3.0f*t-2.0f*t*i); 01210 } 01211 visifac*= inpr; 01212 } 01213 } 01214 } 01215 } 01216 if (visifac <= 0.001) visifac = 0.0f; 01217 return visifac; 01218 } 01219 } 01220 01221 /* function returns raw diff, spec and full shadowed diff in the 'shad' pass */ 01222 static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int passflag) 01223 { 01224 Material *ma= shi->mat; 01225 VlakRen *vlr= shi->vlr; 01226 float lv[3], lampdist, lacol[3], shadfac[4], lashdw[3]; 01227 float i, is, i_noshad, inp, *vn, *view, vnor[3], phongcorr=1.0f; 01228 float visifac; 01229 01230 vn= shi->vn; 01231 view= shi->view; 01232 01233 01234 if (lar->energy == 0.0) return; 01235 /* only shadow lamps shouldn't affect shadow-less materials at all */ 01236 if ((lar->mode & LA_ONLYSHADOW) && (!(ma->mode & MA_SHADOW) || !(R.r.mode & R_SHADOW))) 01237 return; 01238 /* optimisation, don't render fully black lamps */ 01239 if (!(lar->mode & LA_TEXTURE) && (lar->r + lar->g + lar->b == 0.0f)) 01240 return; 01241 01242 /* lampdist, spot angle, area side, ... */ 01243 visifac= lamp_get_visibility(lar, shi->co, lv, &lampdist); 01244 if(visifac==0.0f) 01245 return; 01246 01247 if(lar->type==LA_SPOT) { 01248 if(lar->mode & LA_OSATEX) { 01249 shi->osatex= 1; /* signal for multitex() */ 01250 01251 shi->dxlv[0]= lv[0] - (shi->co[0]-lar->co[0]+shi->dxco[0])/lampdist; 01252 shi->dxlv[1]= lv[1] - (shi->co[1]-lar->co[1]+shi->dxco[1])/lampdist; 01253 shi->dxlv[2]= lv[2] - (shi->co[2]-lar->co[2]+shi->dxco[2])/lampdist; 01254 01255 shi->dylv[0]= lv[0] - (shi->co[0]-lar->co[0]+shi->dyco[0])/lampdist; 01256 shi->dylv[1]= lv[1] - (shi->co[1]-lar->co[1]+shi->dyco[1])/lampdist; 01257 shi->dylv[2]= lv[2] - (shi->co[2]-lar->co[2]+shi->dyco[2])/lampdist; 01258 } 01259 } 01260 01261 /* lamp color texture */ 01262 lacol[0]= lar->r; 01263 lacol[1]= lar->g; 01264 lacol[2]= lar->b; 01265 01266 lashdw[0]= lar->shdwr; 01267 lashdw[1]= lar->shdwg; 01268 lashdw[2]= lar->shdwb; 01269 01270 if(lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv, shi, lacol, LA_TEXTURE); 01271 if(lar->mode & LA_SHAD_TEX) do_lamp_tex(lar, lv, shi, lashdw, LA_SHAD_TEX); 01272 01273 /* tangent case; calculate fake face normal, aligned with lampvector */ 01274 /* note, vnor==vn is used as tangent trigger for buffer shadow */ 01275 if(vlr->flag & R_TANGENT) { 01276 float cross[3], nstrand[3], blend; 01277 01278 if(ma->mode & MA_STR_SURFDIFF) { 01279 cross_v3_v3v3(cross, shi->surfnor, vn); 01280 cross_v3_v3v3(nstrand, vn, cross); 01281 01282 blend= INPR(nstrand, shi->surfnor); 01283 blend= 1.0f - blend; 01284 CLAMP(blend, 0.0f, 1.0f); 01285 01286 interp_v3_v3v3(vnor, nstrand, shi->surfnor, blend); 01287 normalize_v3(vnor); 01288 } 01289 else { 01290 cross_v3_v3v3(cross, lv, vn); 01291 cross_v3_v3v3(vnor, cross, vn); 01292 normalize_v3(vnor); 01293 } 01294 01295 if(ma->strand_surfnor > 0.0f) { 01296 if(ma->strand_surfnor > shi->surfdist) { 01297 blend= (ma->strand_surfnor - shi->surfdist)/ma->strand_surfnor; 01298 interp_v3_v3v3(vnor, vnor, shi->surfnor, blend); 01299 normalize_v3(vnor); 01300 } 01301 } 01302 01303 vnor[0]= -vnor[0];vnor[1]= -vnor[1];vnor[2]= -vnor[2]; 01304 vn= vnor; 01305 } 01306 else if (ma->mode & MA_TANGENT_V) { 01307 float cross[3]; 01308 cross_v3_v3v3(cross, lv, shi->tang); 01309 cross_v3_v3v3(vnor, cross, shi->tang); 01310 normalize_v3(vnor); 01311 vnor[0]= -vnor[0];vnor[1]= -vnor[1];vnor[2]= -vnor[2]; 01312 vn= vnor; 01313 } 01314 01315 /* dot product and reflectivity */ 01316 /* inp = dotproduct, is = shader result, i = lamp energy (with shadow), i_noshad = i without shadow */ 01317 inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]; 01318 01319 /* phong threshold to prevent backfacing faces having artefacts on ray shadow (terminator problem) */ 01320 /* this complex construction screams for a nicer implementation! (ton) */ 01321 if(R.r.mode & R_SHADOW) { 01322 if(ma->mode & MA_SHADOW) { 01323 if(lar->type==LA_HEMI || lar->type==LA_AREA); 01324 else if((ma->mode & MA_RAYBIAS) && (lar->mode & LA_SHAD_RAY) && (vlr->flag & R_SMOOTH)) { 01325 float thresh= shi->obr->ob->smoothresh; 01326 if(inp>thresh) 01327 phongcorr= (inp-thresh)/(inp*(1.0f-thresh)); 01328 else 01329 phongcorr= 0.0f; 01330 } 01331 else if(ma->sbias!=0.0f && ((lar->mode & LA_SHAD_RAY) || lar->shb)) { 01332 if(inp>ma->sbias) 01333 phongcorr= (inp-ma->sbias)/(inp*(1.0f-ma->sbias)); 01334 else 01335 phongcorr= 0.0f; 01336 } 01337 } 01338 } 01339 01340 /* diffuse shaders */ 01341 if(lar->mode & LA_NO_DIFF) { 01342 is= 0.0f; // skip shaders 01343 } 01344 else if(lar->type==LA_HEMI) { 01345 is= 0.5f*inp + 0.5f; 01346 } 01347 else { 01348 01349 if(lar->type==LA_AREA) 01350 inp= area_lamp_energy_multisample(lar, shi->co, vn); 01351 01352 /* diffuse shaders (oren nayer gets inp from area light) */ 01353 if(ma->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff(inp, vn, lv, view, ma->roughness); 01354 else if(ma->diff_shader==MA_DIFF_TOON) is= Toon_Diff(vn, lv, view, ma->param[0], ma->param[1]); 01355 else if(ma->diff_shader==MA_DIFF_MINNAERT) is= Minnaert_Diff(inp, vn, view, ma->darkness); 01356 else if(ma->diff_shader==MA_DIFF_FRESNEL) is= Fresnel_Diff(vn, lv, view, ma->param[0], ma->param[1]); 01357 else is= inp; // Lambert 01358 } 01359 01360 /* 'is' is diffuse */ 01361 if((ma->shade_flag & MA_CUBIC) && is>0.0f && is<1.0f) 01362 is= 3.0*is*is - 2.0*is*is*is; // nicer termination of shades 01363 01364 i= is*phongcorr; 01365 01366 if(i>0.0f) { 01367 i*= visifac*shi->refl; 01368 } 01369 i_noshad= i; 01370 01371 vn= shi->vn; // bring back original vector, we use special specular shaders for tangent 01372 if(ma->mode & MA_TANGENT_V) 01373 vn= shi->tang; 01374 01375 /* init transp shadow */ 01376 shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 1.0f; 01377 01378 /* shadow and spec, (visifac==0 outside spot) */ 01379 if(visifac> 0.0f) { 01380 01381 if((R.r.mode & R_SHADOW)) { 01382 if(ma->mode & MA_SHADOW) { 01383 if(lar->shb || (lar->mode & LA_SHAD_RAY)) { 01384 01385 if(vn==vnor) /* tangent trigger */ 01386 lamp_get_shadow(lar, shi, INPR(shi->vn, lv), shadfac, shi->depth); 01387 else 01388 lamp_get_shadow(lar, shi, inp, shadfac, shi->depth); 01389 01390 /* warning, here it skips the loop */ 01391 if((lar->mode & LA_ONLYSHADOW) && i>0.0) { 01392 01393 shadfac[3]= i*lar->energy*(1.0f-shadfac[3]); 01394 shr->shad[0] -= shadfac[3]*shi->r*(1.0f-lashdw[0]); 01395 shr->shad[1] -= shadfac[3]*shi->g*(1.0f-lashdw[1]); 01396 shr->shad[2] -= shadfac[3]*shi->b*(1.0f-lashdw[2]); 01397 01398 shr->spec[0] -= shadfac[3]*shi->specr*(1.0f-lashdw[0]); 01399 shr->spec[1] -= shadfac[3]*shi->specg*(1.0f-lashdw[1]); 01400 shr->spec[2] -= shadfac[3]*shi->specb*(1.0f-lashdw[2]); 01401 01402 return; 01403 } 01404 01405 i*= shadfac[3]; 01406 shr->shad[3] = shadfac[3]; /* store this for possible check in troublesome cases */ 01407 } 01408 } 01409 } 01410 01411 /* in case 'no diffuse' we still do most calculus, spec can be in shadow.*/ 01412 if(!(lar->mode & LA_NO_DIFF)) { 01413 if(i>0.0f) { 01414 if(ma->mode & MA_SHADOW_TRA) 01415 add_to_diffuse(shr->shad, shi, is, i*shadfac[0]*lacol[0], i*shadfac[1]*lacol[1], i*shadfac[2]*lacol[2]); 01416 else 01417 add_to_diffuse(shr->shad, shi, is, i*lacol[0], i*lacol[1], i*lacol[2]); 01418 } 01419 /* add light for colored shadow */ 01420 if (i_noshad>i && !(lashdw[0]==0 && lashdw[1]==0 && lashdw[2]==0)) { 01421 add_to_diffuse(shr->shad, shi, is, lashdw[0]*(i_noshad-i)*lacol[0], lashdw[1]*(i_noshad-i)*lacol[1], lashdw[2]*(i_noshad-i)*lacol[2]); 01422 } 01423 if(i_noshad>0.0f) { 01424 if(passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW)) { 01425 add_to_diffuse(shr->diff, shi, is, i_noshad*lacol[0], i_noshad*lacol[1], i_noshad*lacol[2]); 01426 } 01427 else 01428 VECCOPY(shr->diff, shr->shad); 01429 } 01430 } 01431 01432 /* specularity */ 01433 shadfac[3]*= phongcorr; /* note, shadfac not allowed to be stored nonlocal */ 01434 01435 if(shadfac[3]>0.0f && shi->spec!=0.0f && !(lar->mode & LA_NO_SPEC) && !(lar->mode & LA_ONLYSHADOW)) { 01436 01437 if(!(passflag & (SCE_PASS_COMBINED|SCE_PASS_SPEC))); 01438 else if(lar->type==LA_HEMI) { 01439 float t; 01440 /* hemi uses no spec shaders (yet) */ 01441 01442 lv[0]+= view[0]; 01443 lv[1]+= view[1]; 01444 lv[2]+= view[2]; 01445 01446 normalize_v3(lv); 01447 01448 t= vn[0]*lv[0]+vn[1]*lv[1]+vn[2]*lv[2]; 01449 01450 if(lar->type==LA_HEMI) { 01451 t= 0.5*t+0.5; 01452 } 01453 01454 t= shadfac[3]*shi->spec*spec(t, shi->har); 01455 01456 shr->spec[0]+= t*(lacol[0] * shi->specr); 01457 shr->spec[1]+= t*(lacol[1] * shi->specg); 01458 shr->spec[2]+= t*(lacol[2] * shi->specb); 01459 } 01460 else { 01461 /* specular shaders */ 01462 float specfac, t; 01463 01464 if(ma->spec_shader==MA_SPEC_PHONG) 01465 specfac= Phong_Spec(vn, lv, view, shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V)); 01466 else if(ma->spec_shader==MA_SPEC_COOKTORR) 01467 specfac= CookTorr_Spec(vn, lv, view, shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V)); 01468 else if(ma->spec_shader==MA_SPEC_BLINN) 01469 specfac= Blinn_Spec(vn, lv, view, ma->refrac, (float)shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V)); 01470 else if(ma->spec_shader==MA_SPEC_WARDISO) 01471 specfac= WardIso_Spec( vn, lv, view, ma->rms, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V)); 01472 else 01473 specfac= Toon_Spec(vn, lv, view, ma->param[2], ma->param[3], (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V)); 01474 01475 /* area lamp correction */ 01476 if(lar->type==LA_AREA) specfac*= inp; 01477 01478 t= shadfac[3]*shi->spec*visifac*specfac; 01479 01480 if(ma->mode & MA_RAMP_SPEC) { 01481 float spec[3]; 01482 do_specular_ramp(shi, specfac, t, spec); 01483 shr->spec[0]+= t*(lacol[0] * spec[0]); 01484 shr->spec[1]+= t*(lacol[1] * spec[1]); 01485 shr->spec[2]+= t*(lacol[2] * spec[2]); 01486 } 01487 else { 01488 shr->spec[0]+= t*(lacol[0] * shi->specr); 01489 shr->spec[1]+= t*(lacol[1] * shi->specg); 01490 shr->spec[2]+= t*(lacol[2] * shi->specb); 01491 } 01492 } 01493 } 01494 } 01495 } 01496 01497 static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr) 01498 { 01499 01500 if(R.r.mode & R_SHADOW) { 01501 ListBase *lights; 01502 LampRen *lar; 01503 GroupObject *go; 01504 float inpr, lv[3]; 01505 float *view, shadfac[4]; 01506 float ir, accum, visifac, lampdist; 01507 float shaded = 0.0f, lightness = 0.0f; 01508 01509 01510 view= shi->view; 01511 accum= ir= 0.0f; 01512 01513 lights= get_lights(shi); 01514 for(go=lights->first; go; go= go->next) { 01515 lar= go->lampren; 01516 if(lar==NULL) continue; 01517 01518 /* yafray: ignore shading by photonlights, not used in Blender */ 01519 if (lar->type==LA_YF_PHOTON) continue; 01520 01521 if(lar->mode & LA_LAYER) if((lar->lay & shi->obi->lay)==0) continue; 01522 if((lar->lay & shi->lay)==0) continue; 01523 01524 if(lar->shb || (lar->mode & LA_SHAD_RAY)) { 01525 visifac= lamp_get_visibility(lar, shi->co, lv, &lampdist); 01526 ir+= 1.0f; 01527 01528 if(visifac <= 0.0f) { 01529 if (shi->mat->shadowonly_flag == MA_SO_OLD) 01530 accum+= 1.0f; 01531 01532 continue; 01533 } 01534 inpr= INPR(shi->vn, lv); 01535 if(inpr <= 0.0f) { 01536 if (shi->mat->shadowonly_flag == MA_SO_OLD) 01537 accum+= 1.0f; 01538 01539 continue; 01540 } 01541 01542 lamp_get_shadow(lar, shi, inpr, shadfac, shi->depth); 01543 01544 if (shi->mat->shadowonly_flag == MA_SO_OLD) { 01545 /* Old "Shadows Only" */ 01546 accum+= (1.0f-visifac) + (visifac)*rgb_to_grayscale(shadfac)*shadfac[3]; 01547 } 01548 else { 01549 shaded += rgb_to_grayscale(shadfac)*shadfac[3] * visifac * lar->energy; 01550 01551 if (shi->mat->shadowonly_flag == MA_SO_SHADOW) { 01552 lightness += visifac * lar->energy; 01553 } 01554 } 01555 } 01556 } 01557 01558 /* Apply shadows as alpha */ 01559 if(ir>0.0f) { 01560 if (shi->mat->shadowonly_flag == MA_SO_OLD) { 01561 accum = 1.0f - accum/ir; 01562 } 01563 else { 01564 if (shi->mat->shadowonly_flag == MA_SO_SHADOW) { 01565 if (lightness > 0.0f) { 01566 /* Get shadow value from between 0.0f and non-shadowed lightness */ 01567 accum = (lightness - shaded) / (lightness); 01568 } 01569 else { 01570 accum = 0.0f; 01571 } 01572 } 01573 else { /* shadowonly_flag == MA_SO_SHADED */ 01574 /* Use shaded value */ 01575 accum = 1.0f - shaded; 01576 }} 01577 01578 shr->alpha= (shi->alpha)*(accum); 01579 if (shr->alpha<0.0f) shr->alpha=0.0f; 01580 } 01581 else { 01582 /* If "fully shaded", use full alpha even on areas that have no lights */ 01583 if (shi->mat->shadowonly_flag == MA_SO_SHADED) shr->alpha=shi->alpha; 01584 else shr->alpha= 0.f; 01585 } 01586 } 01587 01588 /* quite disputable this... also note it doesn't mirror-raytrace */ 01589 if((R.wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT)) && shi->amb!=0.0f) { 01590 float f; 01591 01592 if(R.wrld.mode & WO_AMB_OCC) { 01593 f= R.wrld.aoenergy*shi->amb; 01594 01595 if(R.wrld.aomix==WO_AOADD) { 01596 if (shi->mat->shadowonly_flag == MA_SO_OLD) { 01597 f= f*(1.0f - rgb_to_grayscale(shi->ao)); 01598 shr->alpha= (shr->alpha + f)*f; 01599 } 01600 else { 01601 shr->alpha -= f*rgb_to_grayscale(shi->ao); 01602 if (shr->alpha<0.0f) shr->alpha=0.0f; 01603 } 01604 } 01605 else /* AO Multiply */ 01606 shr->alpha= (1.0f - f)*shr->alpha + f*(1.0f - (1.0f - shr->alpha)*rgb_to_grayscale(shi->ao)); 01607 } 01608 01609 if(R.wrld.mode & WO_ENV_LIGHT) { 01610 if (shi->mat->shadowonly_flag == MA_SO_OLD) { 01611 f= R.wrld.ao_env_energy*shi->amb*(1.0f - rgb_to_grayscale(shi->env)); 01612 shr->alpha= (shr->alpha + f)*f; 01613 } 01614 else { 01615 f= R.wrld.ao_env_energy*shi->amb; 01616 shr->alpha -= f*rgb_to_grayscale(shi->env); 01617 if (shr->alpha<0.0f) shr->alpha=0.0f; 01618 } 01619 } 01620 } 01621 } 01622 01623 /* let's map negative light as if it mirrors positive light, otherwise negative values disappear */ 01624 static void wrld_exposure_correct(float *diff) 01625 { 01626 01627 diff[0]= R.wrld.linfac*(1.0f-exp( diff[0]*R.wrld.logfac) ); 01628 diff[1]= R.wrld.linfac*(1.0f-exp( diff[1]*R.wrld.logfac) ); 01629 diff[2]= R.wrld.linfac*(1.0f-exp( diff[2]*R.wrld.logfac) ); 01630 } 01631 01632 void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) 01633 { 01634 Material *ma= shi->mat; 01635 int passflag= shi->passflag; 01636 01637 memset(shr, 0, sizeof(ShadeResult)); 01638 01639 if(!(shi->mode & MA_TRANSP)) shi->alpha = 1.0f; 01640 01641 /* separate loop */ 01642 if(ma->mode & MA_ONLYSHADOW) { 01643 shade_lamp_loop_only_shadow(shi, shr); 01644 return; 01645 } 01646 01647 /* envmap hack, always reset */ 01648 shi->refcol[0]= shi->refcol[1]= shi->refcol[2]= shi->refcol[3]= 0.0f; 01649 01650 /* material color itself */ 01651 if(passflag & (SCE_PASS_COMBINED|SCE_PASS_RGBA)) { 01652 if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) { 01653 shi->r= shi->vcol[0]; 01654 shi->g= shi->vcol[1]; 01655 shi->b= shi->vcol[2]; 01656 if(ma->mode & (MA_FACETEXTURE_ALPHA)) 01657 shi->alpha= (shi->mode & MA_TRANSP) ? shi->vcol[3] : 1.0f; 01658 } 01659 if(ma->texco){ 01660 do_material_tex(shi); 01661 if (!(shi->mode & MA_TRANSP)) shi->alpha = 1.0f; 01662 } 01663 01664 shr->col[0]= shi->r*shi->alpha; 01665 shr->col[1]= shi->g*shi->alpha; 01666 shr->col[2]= shi->b*shi->alpha; 01667 shr->col[3]= shi->alpha; 01668 01669 if((ma->sss_flag & MA_DIFF_SSS) && !sss_pass_done(&R, ma)) { 01670 if(ma->sss_texfac == 0.0f) { 01671 shi->r= shi->g= shi->b= shi->alpha= 1.0f; 01672 shr->col[0]= shr->col[1]= shr->col[2]= shr->col[3]= 1.0f; 01673 } 01674 else { 01675 shi->r= pow(shi->r, ma->sss_texfac); 01676 shi->g= pow(shi->g, ma->sss_texfac); 01677 shi->b= pow(shi->b, ma->sss_texfac); 01678 shi->alpha= pow(shi->alpha, ma->sss_texfac); 01679 01680 shr->col[0]= pow(shr->col[0], ma->sss_texfac); 01681 shr->col[1]= pow(shr->col[1], ma->sss_texfac); 01682 shr->col[2]= pow(shr->col[2], ma->sss_texfac); 01683 shr->col[3]= pow(shr->col[3], ma->sss_texfac); 01684 } 01685 } 01686 } 01687 01688 if(ma->mode & MA_SHLESS) { 01689 shr->combined[0]= shi->r; 01690 shr->combined[1]= shi->g; 01691 shr->combined[2]= shi->b; 01692 shr->alpha= shi->alpha; 01693 return; 01694 } 01695 01696 if( (ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))== MA_VERTEXCOL ) { // vertexcolor light 01697 shr->emit[0]= shi->r*(shi->emit+shi->vcol[0]); 01698 shr->emit[1]= shi->g*(shi->emit+shi->vcol[1]); 01699 shr->emit[2]= shi->b*(shi->emit+shi->vcol[2]); 01700 } 01701 else { 01702 shr->emit[0]= shi->r*shi->emit; 01703 shr->emit[1]= shi->g*shi->emit; 01704 shr->emit[2]= shi->b*shi->emit; 01705 } 01706 01707 /* AO pass */ 01708 if(R.wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) { 01709 if(((passflag & SCE_PASS_COMBINED) && (shi->combinedflag & (SCE_PASS_AO|SCE_PASS_ENVIRONMENT|SCE_PASS_INDIRECT))) 01710 || (passflag & (SCE_PASS_AO|SCE_PASS_ENVIRONMENT|SCE_PASS_INDIRECT))) { 01711 if(R.r.mode & R_SHADOW) { 01712 /* AO was calculated for scanline already */ 01713 if(shi->depth || shi->volume_depth) 01714 ambient_occlusion(shi); 01715 VECCOPY(shr->ao, shi->ao); 01716 VECCOPY(shr->env, shi->env); // XXX multiply 01717 VECCOPY(shr->indirect, shi->indirect); // XXX multiply 01718 } 01719 } 01720 } 01721 01722 /* lighting pass */ 01723 if(passflag & (SCE_PASS_COMBINED|SCE_PASS_DIFFUSE|SCE_PASS_SPEC|SCE_PASS_SHADOW)) { 01724 GroupObject *go; 01725 ListBase *lights; 01726 LampRen *lar; 01727 01728 lights= get_lights(shi); 01729 for(go=lights->first; go; go= go->next) { 01730 lar= go->lampren; 01731 if(lar==NULL) continue; 01732 01733 /* yafray: ignore shading by photonlights, not used in Blender */ 01734 if (lar->type==LA_YF_PHOTON) continue; 01735 01736 /* test for lamp layer */ 01737 if(lar->mode & LA_LAYER) if((lar->lay & shi->obi->lay)==0) continue; 01738 if((lar->lay & shi->lay)==0) continue; 01739 01740 /* accumulates in shr->diff and shr->spec and shr->shad (diffuse with shadow!) */ 01741 shade_one_light(lar, shi, shr, passflag); 01742 } 01743 01744 /*this check is to prevent only shadow lamps from producing negative 01745 colors.*/ 01746 if (shr->spec[0] < 0) shr->spec[0] = 0; 01747 if (shr->spec[1] < 0) shr->spec[1] = 0; 01748 if (shr->spec[2] < 0) shr->spec[2] = 0; 01749 01750 if (shr->shad[0] < 0) shr->shad[0] = 0; 01751 if (shr->shad[1] < 0) shr->shad[1] = 0; 01752 if (shr->shad[2] < 0) shr->shad[2] = 0; 01753 01754 if(ma->sss_flag & MA_DIFF_SSS) { 01755 float sss[3], col[3], invalpha, texfac= ma->sss_texfac; 01756 01757 /* this will return false in the preprocess stage */ 01758 if(sample_sss(&R, ma, shi->co, sss)) { 01759 invalpha= (shr->col[3] > FLT_EPSILON)? 1.0f/shr->col[3]: 1.0f; 01760 01761 if(texfac==0.0f) { 01762 VECCOPY(col, shr->col); 01763 mul_v3_fl(col, invalpha); 01764 } 01765 else if(texfac==1.0f) { 01766 col[0]= col[1]= col[2]= 1.0f; 01767 mul_v3_fl(col, invalpha); 01768 } 01769 else { 01770 VECCOPY(col, shr->col); 01771 mul_v3_fl(col, invalpha); 01772 col[0]= pow(col[0], 1.0f-texfac); 01773 col[1]= pow(col[1], 1.0f-texfac); 01774 col[2]= pow(col[2], 1.0f-texfac); 01775 } 01776 01777 shr->diff[0]= sss[0]*col[0]; 01778 shr->diff[1]= sss[1]*col[1]; 01779 shr->diff[2]= sss[2]*col[2]; 01780 01781 if(shi->combinedflag & SCE_PASS_SHADOW) { 01782 shr->shad[0]= shr->diff[0]; 01783 shr->shad[1]= shr->diff[1]; 01784 shr->shad[2]= shr->diff[2]; 01785 } 01786 } 01787 } 01788 01789 if(shi->combinedflag & SCE_PASS_SHADOW) 01790 VECCOPY(shr->combined, shr->shad) /* note, no ';' ! */ 01791 else 01792 VECCOPY(shr->combined, shr->diff); 01793 01794 /* calculate shadow pass, we use a multiplication mask */ 01795 /* if diff = 0,0,0 it doesn't matter what the shadow pass is, so leave it as is */ 01796 if(passflag & SCE_PASS_SHADOW && !(shr->diff[0]==0.0f && shr->diff[1]==0.0f && shr->diff[2]==0.0f)) { 01797 if(shr->diff[0]!=0.0f) shr->shad[0]= shr->shad[0]/shr->diff[0]; 01798 /* can't determine proper shadow from shad/diff (0/0), so use shadow intensity */ 01799 else if(shr->shad[0]==0.0f) shr->shad[0]= shr->shad[3]; 01800 01801 if(shr->diff[1]!=0.0f) shr->shad[1]= shr->shad[1]/shr->diff[1]; 01802 else if(shr->shad[1]==0.0f) shr->shad[1]= shr->shad[3]; 01803 01804 if(shr->diff[2]!=0.0f) shr->shad[2]= shr->shad[2]/shr->diff[2]; 01805 else if(shr->shad[2]==0.0f) shr->shad[2]= shr->shad[3]; 01806 } 01807 01808 /* exposure correction */ 01809 if((R.wrld.exp!=0.0f || R.wrld.range!=1.0f) && !R.sss_points) { 01810 wrld_exposure_correct(shr->combined); /* has no spec! */ 01811 wrld_exposure_correct(shr->spec); 01812 } 01813 } 01814 01815 /* alpha in end, spec can influence it */ 01816 if(passflag & (SCE_PASS_COMBINED)) { 01817 if((ma->fresnel_tra!=0.0f) && (shi->mode & MA_TRANSP)) 01818 shi->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra); 01819 01820 /* note: shi->mode! */ 01821 if(shi->mode & MA_TRANSP && (shi->mode & (MA_ZTRANSP|MA_RAYTRANSP))) { 01822 if(shi->spectra!=0.0f) { 01823 float t = MAX3(shr->spec[0], shr->spec[1], shr->spec[2]); 01824 t *= shi->spectra; 01825 if(t>1.0f) t= 1.0f; 01826 shi->alpha= (1.0f-t)*shi->alpha+t; 01827 } 01828 } 01829 } 01830 shr->alpha= shi->alpha; 01831 01832 /* from now stuff everything in shr->combined: ambient, AO, radio, ramps, exposure */ 01833 if(!(ma->sss_flag & MA_DIFF_SSS) || !sss_pass_done(&R, ma)) { 01834 if(R.r.mode & R_SHADOW) { 01835 /* add AO in combined? */ 01836 if(R.wrld.mode & WO_AMB_OCC) 01837 if(shi->combinedflag & SCE_PASS_AO) 01838 ambient_occlusion_apply(shi, shr); 01839 01840 if(R.wrld.mode & WO_ENV_LIGHT) 01841 if(shi->combinedflag & SCE_PASS_ENVIRONMENT) 01842 environment_lighting_apply(shi, shr); 01843 01844 if(R.wrld.mode & WO_INDIRECT_LIGHT) 01845 if(shi->combinedflag & SCE_PASS_INDIRECT) 01846 indirect_lighting_apply(shi, shr); 01847 } 01848 01849 shr->combined[0]+= shi->ambr; 01850 shr->combined[1]+= shi->ambg; 01851 shr->combined[2]+= shi->ambb; 01852 01853 if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(shr->combined, shi); 01854 } 01855 01856 if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(shr->spec, shr->spec+1, shr->spec+2, shi); 01857 01858 /* refcol is for envmap only */ 01859 if(shi->refcol[0]!=0.0f) { 01860 float result[3]; 01861 01862 result[0]= shi->mirr*shi->refcol[1] + (1.0f - shi->mirr*shi->refcol[0])*shr->combined[0]; 01863 result[1]= shi->mirg*shi->refcol[2] + (1.0f - shi->mirg*shi->refcol[0])*shr->combined[1]; 01864 result[2]= shi->mirb*shi->refcol[3] + (1.0f - shi->mirb*shi->refcol[0])*shr->combined[2]; 01865 01866 if(passflag & SCE_PASS_REFLECT) 01867 VECSUB(shr->refl, result, shr->combined); 01868 01869 if(shi->combinedflag & SCE_PASS_REFLECT) 01870 VECCOPY(shr->combined, result); 01871 01872 } 01873 01874 /* and add emit and spec */ 01875 if(shi->combinedflag & SCE_PASS_EMIT) 01876 VECADD(shr->combined, shr->combined, shr->emit); 01877 if(shi->combinedflag & SCE_PASS_SPEC) 01878 VECADD(shr->combined, shr->combined, shr->spec); 01879 01880 /* modulate by the object color */ 01881 if((ma->shade_flag & MA_OBCOLOR) && shi->obr->ob) { 01882 if(!(ma->sss_flag & MA_DIFF_SSS) || !sss_pass_done(&R, ma)) { 01883 float obcol[4]; 01884 01885 QUATCOPY(obcol, shi->obr->ob->col); 01886 CLAMP(obcol[3], 0.0f, 1.0f); 01887 01888 shr->combined[0] *= obcol[0]; 01889 shr->combined[1] *= obcol[1]; 01890 shr->combined[2] *= obcol[2]; 01891 if (shi->mode & MA_TRANSP) shr->alpha *= obcol[3]; 01892 } 01893 } 01894 01895 shr->combined[3]= shr->alpha; 01896 } 01897