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