4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2006 Blender Foundation
21 * All rights reserved.
23 * Contributors: Hos, Robert Wenzlaff.
25 * ***** END GPL LICENSE BLOCK *****
33 #include "MTC_matrixops.h"
34 #include "BLI_arithb.h"
36 #include "BKE_colortools.h"
37 #include "BKE_material.h"
38 #include "BKE_texture.h"
39 #include "BKE_utildefines.h"
41 #include "DNA_group_types.h"
42 #include "DNA_lamp_types.h"
43 #include "DNA_material_types.h"
46 #include "renderpipeline.h"
47 #include "render_types.h"
48 #include "pixelblending.h"
49 #include "rendercore.h"
54 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
55 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
56 /* only to be used here in this file, it's for speed */
57 extern struct Render R
;
58 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
60 static ListBase
*get_lights(ShadeInput
*shi
)
63 if(shi
->light_override
)
64 return &shi
->light_override
->gobject
;
65 else if(shi
->mat
&& shi
->mat
->group
)
66 return &shi
->mat
->group
->gobject
;
72 static void fogcolor(float *colf
, float *rco
, float *view
)
74 float alpha
, stepsize
, startdist
, dist
, hor
[4], zen
[3], vec
[3], dview
[3];
75 float div
=0.0f
, distfac
;
77 hor
[0]= R
.wrld
.horr
; hor
[1]= R
.wrld
.horg
; hor
[2]= R
.wrld
.horb
;
78 zen
[0]= R
.wrld
.zenr
; zen
[1]= R
.wrld
.zeng
; zen
[2]= R
.wrld
.zenb
;
82 /* we loop from cur coord to mist start in steps */
86 dview
[0]= view
[0]/(stepsize
*div
);
87 dview
[1]= view
[1]/(stepsize
*div
);
90 startdist
= -rco
[2] + BLI_frand();
91 for(dist
= startdist
; dist
>R
.wrld
.miststa
; dist
-= stepsize
) {
93 hor
[0]= R
.wrld
.horr
; hor
[1]= R
.wrld
.horg
; hor
[2]= R
.wrld
.horb
;
95 do_sky_tex(vec
, vec
, NULL
, hor
, zen
, &alpha
);
97 distfac
= (dist
-R
.wrld
.miststa
)/R
.wrld
.mistdist
;
99 hor
[3]= hor
[0]*distfac
*distfac
;
103 hor
[0]= hor
[0]*alpha
;
104 hor
[1]= hor
[1]*alpha
;
105 hor
[2]= hor
[2]*alpha
;
106 addAlphaOverFloat(colf
, hor
);
108 VECSUB(vec
, vec
, dview
);
113 /* zcor is distance, co the 3d coordinate in eye space, return alpha */
114 float mistfactor(float zcor
, float *co
)
118 fac
= zcor
- R
.wrld
.miststa
; /* zcor is calculated per pixel */
120 /* fac= -co[2]-R.wrld.miststa; */
123 if(fac
< R
.wrld
.mistdist
) {
125 fac
= (fac
/(R
.wrld
.mistdist
));
127 if(R
.wrld
.mistype
==0) fac
*= fac
;
128 else if(R
.wrld
.mistype
==1);
135 /* height switched off mist */
136 if(R
.wrld
.misthi
!=0.0f
&& fac
!=0.0f
) {
137 /* at height misthi the mist is completely gone */
139 hi
= R
.viewinv
[0][2]*co
[0]+R
.viewinv
[1][2]*co
[1]+R
.viewinv
[2][2]*co
[2]+R
.viewinv
[3][2];
141 if(hi
>R
.wrld
.misthi
) fac
= 0.0f
;
143 hi
= (R
.wrld
.misthi
-hi
)/R
.wrld
.misthi
;
148 return (1.0f
-fac
)* (1.0f
-R
.wrld
.misi
);
151 static void spothalo(struct LampRen
*lar
, ShadeInput
*shi
, float *intens
)
153 double a
, b
, c
, disc
, nray
[3], npos
[3];
154 float t0
, t1
= 0.0f
, t2
= 0.0f
, t3
, haint
;
155 float p1
[3], p2
[3], ladist
, maxz
= 0.0f
, maxy
= 0.0f
;
156 int snijp
, doclip
=1, use_yco
=0;
162 if(R
.r
.mode
& R_ORTHO
) {
163 /* camera pos (view vector) cannot be used... */
164 /* camera position (cox,coy,0) rotate around lamp */
165 p1
[0]= shi
->co
[0]-lar
->co
[0];
166 p1
[1]= shi
->co
[1]-lar
->co
[1];
168 MTC_Mat3MulVecfl(lar
->imat
, p1
);
169 VECCOPY(npos
, p1
); // npos is double!
172 npos
[2]*= lar
->sh_zfac
;
175 VECCOPY(npos
, lar
->sh_invcampos
); /* in initlamp calculated */
179 VECCOPY(nray
, shi
->view
);
180 MTC_Mat3MulVecd(lar
->imat
, nray
);
182 if(R
.wrld
.mode
& WO_MIST
) {
184 haint
*= mistfactor(-lar
->co
[2], lar
->co
);
192 if(shi
->co
[2]==0.0f
) doclip
= 0; /* for when halo at sky */
194 p1
[0]= shi
->co
[0]-lar
->co
[0];
195 p1
[1]= shi
->co
[1]-lar
->co
[1];
196 p1
[2]= shi
->co
[2]-lar
->co
[2];
198 maxz
= lar
->imat
[0][2]*p1
[0]+lar
->imat
[1][2]*p1
[1]+lar
->imat
[2][2]*p1
[2];
200 maxy
= lar
->imat
[0][1]*p1
[0]+lar
->imat
[1][1]*p1
[1]+lar
->imat
[2][1]*p1
[2];
202 if( fabs(nray
[2]) < DBL_EPSILON
) use_yco
= 1;
205 /* scale z to make sure volume is normalized */
206 nray
[2]*= lar
->sh_zfac
;
207 /* nray does not need normalization */
209 ladist
= lar
->sh_zfac
*lar
->dist
;
212 a
= nray
[0] * nray
[0] + nray
[1] * nray
[1] - nray
[2]*nray
[2];
213 b
= nray
[0] * npos
[0] + nray
[1] * npos
[1] - nray
[2]*npos
[2];
214 c
= npos
[0] * npos
[0] + npos
[1] * npos
[1] - npos
[2]*npos
[2];
217 if (fabs(a
) < DBL_EPSILON
) {
219 * Only one intersection point...
230 else if (disc
> 0.0) {
232 t1
= (-b
+ disc
) / a
;
233 t2
= (-b
- disc
) / a
;
240 a
= t1
; t1
= t2
; t2
= a
;
243 /* z of intersection points with diabolo */
244 p1
[2]= npos
[2] + t1
*nray
[2];
245 p2
[2]= npos
[2] + t2
*nray
[2];
247 /* evaluate both points */
248 if(p1
[2]<=0.0f
) ok1
= 1;
249 if(p2
[2]<=0.0f
&& t1
!=t2
) ok2
= 1;
251 /* at least 1 point with negative z */
252 if(ok1
==0 && ok2
==0) return;
254 /* intersction point with -ladist, the bottom of the cone */
256 t3
= (-ladist
-npos
[2])/nray
[2];
258 /* de we have to replace one of the intersection points? */
260 if(p1
[2]<-ladist
) t1
= t3
;
267 if(p2
[2]<-ladist
) t2
= t3
;
274 else if(ok1
==0 || ok2
==0) return;
276 /* at least 1 visible interesction point */
277 if(t1
<0.0f
&& t2
<0.0f
) return;
279 if(t1
<0.0f
) t1
= 0.0f
;
280 if(t2
<0.0f
) t2
= 0.0f
;
284 /* sort again to be sure */
286 a
= t1
; t1
= t2
; t2
= a
;
289 /* calculate t0: is the maximum visible z (when halo is intersected by face) */
291 if(use_yco
==0) t0
= (maxz
-npos
[2])/nray
[2];
292 else t0
= (maxy
-npos
[1])/nray
[1];
299 p1
[0]= npos
[0] + t1
*nray
[0];
300 p1
[1]= npos
[1] + t1
*nray
[1];
301 p1
[2]= npos
[2] + t1
*nray
[2];
302 p2
[0]= npos
[0] + t2
*nray
[0];
303 p2
[1]= npos
[1] + t2
*nray
[1];
304 p2
[2]= npos
[2] + t2
*nray
[2];
307 /* now we have 2 points, make three lengths with it */
309 a
= sqrt(p1
[0]*p1
[0]+p1
[1]*p1
[1]+p1
[2]*p1
[2]);
310 b
= sqrt(p2
[0]*p2
[0]+p2
[1]*p2
[1]+p2
[2]*p2
[2]);
319 *intens
= c
*( (1.0-a
)+(1.0-b
) );
321 /* WATCH IT: do not clip a,b en c at 1.0, this gives nasty little overflows
322 at the edges (especially with narrow halos) */
323 if(*intens
<=0.0f
) return;
326 /* not needed because t0 has been used for p1/p2 as well */
327 /* if(doclip && t0<t2) { */
328 /* *intens *= (t0-t1)/(t2-t1); */
333 if(lar
->shb
&& lar
->shb
->shadhalostep
) {
334 *intens
*= shadow_halo(lar
, p1
, p2
);
340 void renderspothalo(ShadeInput
*shi
, float *col
, float alpha
)
347 if(alpha
==0.0f
) return;
349 lights
= get_lights(shi
);
350 for(go
=lights
->first
; go
; go
= go
->next
) {
352 if(lar
==NULL
) continue;
354 if(lar
->type
==LA_SPOT
&& (lar
->mode
& LA_HALO
) && lar
->haint
>0) {
356 if(lar
->mode
& LA_LAYER
)
357 if(shi
->vlr
&& (lar
->lay
& shi
->vlr
->lay
)==0)
359 if((lar
->lay
& shi
->lay
)==0)
362 spothalo(lar
, shi
, &i
);
364 col
[3]+= i
*alpha
; // all premul
365 col
[0]+= i
*lar
->r
*alpha
;
366 col
[1]+= i
*lar
->g
*alpha
;
367 col
[2]+= i
*lar
->b
*alpha
;
371 /* clip alpha, is needed for unified 'alpha threshold' (vanillaRenderPipe.c) */
372 if(col
[3]>1.0f
) col
[3]= 1.0f
;
377 /* ---------------- shaders ----------------------- */
379 static double Normalize_d(double *n
)
383 d
= n
[0]*n
[0]+n
[1]*n
[1]+n
[2]*n
[2];
385 if(d
>0.00000000000000001) {
398 /* mix of 'real' fresnel and allowing control. grad defines blending gradient */
399 float fresnel_fac(float *view
, float *vn
, float grad
, float fac
)
403 if(fac
==0.0f
) return 1.0f
;
405 t1
= (view
[0]*vn
[0] + view
[1]*vn
[1] + view
[2]*vn
[2]);
406 if(t1
>0.0f
) t2
= 1.0f
+t1
;
409 t2
= grad
+ (1.0f
-grad
)*pow(t2
, fac
);
411 if(t2
<0.0f
) return 0.0f
;
412 else if(t2
>1.0f
) return 1.0f
;
416 static double saacos_d(double fac
)
418 if(fac
<= -1.0f
) return M_PI
;
419 else if(fac
>=1.0f
) return 0.0;
420 else return acos(fac
);
423 /* Stoke's form factor. Need doubles here for extreme small area sizes */
424 static float area_lamp_energy(float *co
, float *vn
, LampRen
*lar
)
427 double vec
[4][3]; /* vectors of rendered co to vertices lamp */
428 double cross
[4][3]; /* cross products of this */
429 double rad
[4]; /* angles between vecs */
431 VECSUB(vec
[0], co
, lar
->area
[0]);
432 VECSUB(vec
[1], co
, lar
->area
[1]);
433 VECSUB(vec
[2], co
, lar
->area
[2]);
434 VECSUB(vec
[3], co
, lar
->area
[3]);
442 CROSS(cross
[0], vec
[0], vec
[1]);
443 CROSS(cross
[1], vec
[1], vec
[2]);
444 CROSS(cross
[2], vec
[2], vec
[3]);
445 CROSS(cross
[3], vec
[3], vec
[0]);
447 Normalize_d(cross
[0]);
448 Normalize_d(cross
[1]);
449 Normalize_d(cross
[2]);
450 Normalize_d(cross
[3]);
453 rad
[0]= vec
[0][0]*vec
[1][0]+ vec
[0][1]*vec
[1][1]+ vec
[0][2]*vec
[1][2];
454 rad
[1]= vec
[1][0]*vec
[2][0]+ vec
[1][1]*vec
[2][1]+ vec
[1][2]*vec
[2][2];
455 rad
[2]= vec
[2][0]*vec
[3][0]+ vec
[2][1]*vec
[3][1]+ vec
[2][2]*vec
[3][2];
456 rad
[3]= vec
[3][0]*vec
[0][0]+ vec
[3][1]*vec
[0][1]+ vec
[3][2]*vec
[0][2];
458 rad
[0]= saacos_d(rad
[0]);
459 rad
[1]= saacos_d(rad
[1]);
460 rad
[2]= saacos_d(rad
[2]);
461 rad
[3]= saacos_d(rad
[3]);
464 fac
= rad
[0]*(vn
[0]*cross
[0][0]+ vn
[1]*cross
[0][1]+ vn
[2]*cross
[0][2]);
465 fac
+= rad
[1]*(vn
[0]*cross
[1][0]+ vn
[1]*cross
[1][1]+ vn
[2]*cross
[1][2]);
466 fac
+= rad
[2]*(vn
[0]*cross
[2][0]+ vn
[1]*cross
[2][1]+ vn
[2]*cross
[2][2]);
467 fac
+= rad
[3]*(vn
[0]*cross
[3][0]+ vn
[1]*cross
[3][1]+ vn
[2]*cross
[3][2]);
469 if(fac
<=0.0) return 0.0;
470 return pow(fac
*lar
->areasize
, lar
->k
); // corrected for buttons size and lar->dist^2
473 static float spec(float inp
, int hard
)
477 if(inp
>=1.0f
) return 1.0f
;
478 else if (inp
<=0.0f
) return 0.0f
;
482 if(b1
<0.01f
) b1
= 0.01f
;
484 if((hard
& 1)==0) inp
= 1.0f
;
485 if(hard
& 2) inp
*= b1
;
487 if(hard
& 4) inp
*= b1
;
489 if(hard
& 8) inp
*= b1
;
491 if(hard
& 16) inp
*= b1
;
495 if(b1
<0.001f
) b1
= 0.0f
;
497 if(hard
& 32) inp
*= b1
;
499 if(hard
& 64) inp
*=b1
;
501 if(hard
& 128) inp
*=b1
;
503 if(b1
<0.001f
) b1
= 0.0f
;
513 static float Phong_Spec( float *n
, float *l
, float *v
, int hard
, int tangent
)
523 rslt
= h
[0]*n
[0] + h
[1]*n
[1] + h
[2]*n
[2];
524 if(tangent
) rslt
= sasqrt(1.0f
- rslt
*rslt
);
526 if( rslt
> 0.0f
) rslt
= spec(rslt
, hard
);
533 /* reduced cook torrance spec (for off-specular peak) */
534 static float CookTorr_Spec(float *n
, float *l
, float *v
, int hard
, int tangent
)
536 float i
, nh
, nv
, h
[3];
543 nh
= n
[0]*h
[0]+n
[1]*h
[1]+n
[2]*h
[2];
544 if(tangent
) nh
= sasqrt(1.0f
- nh
*nh
);
545 else if(nh
<0.0f
) return 0.0f
;
547 nv
= n
[0]*v
[0]+n
[1]*v
[1]+n
[2]*v
[2];
548 if(tangent
) nv
= sasqrt(1.0f
- nv
*nv
);
549 else if(nv
<0.0f
) nv
= 0.0f
;
558 static float Blinn_Spec(float *n
, float *l
, float *v
, float refrac
, float spec_power
, int tangent
)
560 float i
, nh
, nv
, nl
, vh
, h
[3];
561 float a
, b
, c
, g
=0.0f
, p
, f
, ang
;
563 if(refrac
< 1.0f
) return 0.0f
;
564 if(spec_power
== 0.0f
) return 0.0f
;
566 /* conversion from 'hardness' (1-255) to 'spec_power' (50 maps at 0.1) */
567 if(spec_power
<100.0f
)
568 spec_power
= sqrt(1.0f
/spec_power
);
569 else spec_power
= 10.0f
/spec_power
;
576 nh
= n
[0]*h
[0]+n
[1]*h
[1]+n
[2]*h
[2]; /* Dot product between surface normal and half-way vector */
577 if(tangent
) nh
= sasqrt(1.0f
- nh
*nh
);
578 else if(nh
<0.0f
) return 0.0f
;
580 nv
= n
[0]*v
[0]+n
[1]*v
[1]+n
[2]*v
[2]; /* Dot product between surface normal and view vector */
581 if(tangent
) nv
= sasqrt(1.0f
- nv
*nv
);
582 if(nv
<=0.01f
) nv
= 0.01f
; /* hrms... */
584 nl
= n
[0]*l
[0]+n
[1]*l
[1]+n
[2]*l
[2]; /* Dot product between surface normal and light vector */
585 if(tangent
) nl
= sasqrt(1.0f
- nl
*nl
);
590 vh
= v
[0]*h
[0]+v
[1]*h
[1]+v
[2]*h
[2]; /* Dot product between view vector and half-way vector */
591 if(vh
<=0.0f
) vh
= 0.01f
;
597 if( a
< b
&& a
< c
) g
= a
;
598 else if( b
< a
&& b
< c
) g
= b
;
599 else if( c
< a
&& c
< b
) g
= c
;
601 p
= sqrt( (double)((refrac
* refrac
)+(vh
*vh
)-1.0f
) );
602 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
))));
605 i
= f
* g
* exp((double)(-(ang
*ang
) / (2.0f
*spec_power
*spec_power
)));
611 /* cartoon render spec */
612 static float Toon_Spec( float *n
, float *l
, float *v
, float size
, float smooth
, int tangent
)
623 rslt
= h
[0]*n
[0] + h
[1]*n
[1] + h
[2]*n
[2];
624 if(tangent
) rslt
= sasqrt(1.0f
- rslt
*rslt
);
626 ang
= saacos( rslt
);
628 if( ang
< size
) rslt
= 1.0f
;
629 else if( ang
>= (size
+ smooth
) || smooth
== 0.0f
) rslt
= 0.0f
;
630 else rslt
= 1.0f
- ((ang
- size
) / smooth
);
635 /* Ward isotropic gaussian spec */
636 static float WardIso_Spec( float *n
, float *l
, float *v
, float rms
, int tangent
)
638 float i
, nh
, nv
, nl
, h
[3], angle
, alpha
;
641 /* half-way vector */
647 nh
= n
[0]*h
[0]+n
[1]*h
[1]+n
[2]*h
[2]; /* Dot product between surface normal and half-way vector */
648 if(tangent
) nh
= sasqrt(1.0f
- nh
*nh
);
649 if(nh
<=0.0f
) nh
= 0.001f
;
651 nv
= n
[0]*v
[0]+n
[1]*v
[1]+n
[2]*v
[2]; /* Dot product between surface normal and view vector */
652 if(tangent
) nv
= sasqrt(1.0f
- nv
*nv
);
653 if(nv
<=0.0f
) nv
= 0.001f
;
655 nl
= n
[0]*l
[0]+n
[1]*l
[1]+n
[2]*l
[2]; /* Dot product between surface normal and light vector */
656 if(tangent
) nl
= sasqrt(1.0f
- nl
*nl
);
657 if(nl
<=0.0f
) nl
= 0.001f
;
659 angle
= tan(saacos(nh
));
660 alpha
= MAX2(rms
, 0.001f
);
662 i
= nl
* (1.0f
/(4.0f
*M_PI
*alpha
*alpha
)) * (exp( -(angle
*angle
)/(alpha
*alpha
))/(sqrt(nv
*nl
)));
667 /* cartoon render diffuse */
668 static float Toon_Diff( float *n
, float *l
, float *v
, float size
, float smooth
)
672 rslt
= n
[0]*l
[0] + n
[1]*l
[1] + n
[2]*l
[2];
674 ang
= saacos( (double)(rslt
) );
676 if( ang
< size
) rslt
= 1.0f
;
677 else if( ang
>= (size
+ smooth
) || smooth
== 0.0f
) rslt
= 0.0f
;
678 else rslt
= 1.0f
- ((ang
- size
) / smooth
);
683 /* Oren Nayar diffuse */
685 /* 'nl' is either dot product, or return value of area light */
686 /* in latter case, only last multiplication uses 'nl' */
687 static float OrenNayar_Diff(float nl
, float *n
, float *l
, float *v
, float rough
)
689 float i
, nh
, nv
, vh
, realnl
, h
[3];
691 float Lit_A
, View_A
, Lit_B
[3], View_B
[3];
698 nh
= n
[0]*h
[0]+n
[1]*h
[1]+n
[2]*h
[2]; /* Dot product between surface normal and half-way vector */
699 if(nh
<0.0f
) nh
= 0.0f
;
701 nv
= n
[0]*v
[0]+n
[1]*v
[1]+n
[2]*v
[2]; /* Dot product between surface normal and view vector */
702 if(nv
<=0.0f
) nv
= 0.0f
;
704 realnl
= n
[0]*l
[0]+n
[1]*l
[1]+n
[2]*l
[2]; /* Dot product between surface normal and light vector */
705 if(realnl
<=0.0f
) return 0.0f
;
706 if(nl
<0.0f
) return 0.0f
; /* value from area light */
708 vh
= v
[0]*h
[0]+v
[1]*h
[1]+v
[2]*h
[2]; /* Dot product between view vector and halfway vector */
709 if(vh
<=0.0f
) vh
= 0.0f
;
711 Lit_A
= saacos(realnl
);
712 View_A
= saacos( nv
);
714 Lit_B
[0] = l
[0] - (realnl
* n
[0]);
715 Lit_B
[1] = l
[1] - (realnl
* n
[1]);
716 Lit_B
[2] = l
[2] - (realnl
* n
[2]);
719 View_B
[0] = v
[0] - (nv
* n
[0]);
720 View_B
[1] = v
[1] - (nv
* n
[1]);
721 View_B
[2] = v
[2] - (nv
* n
[2]);
724 t
= Lit_B
[0]*View_B
[0] + Lit_B
[1]*View_B
[1] + Lit_B
[2]*View_B
[2];
727 if( Lit_A
> View_A
) {
736 A
= 1.0f
- (0.5f
* ((rough
* rough
) / ((rough
* rough
) + 0.33f
)));
737 B
= 0.45f
* ((rough
* rough
) / ((rough
* rough
) + 0.09f
));
739 b
*= 0.95f
; /* prevent tangens from shooting to inf, 'nl' can be not a dot product here. */
740 /* overflow only happens with extreme size area light, and higher roughness */
741 i
= nl
* ( A
+ ( B
* t
* sin(a
) * tan(b
) ) );
746 /* Minnaert diffuse */
747 static float Minnaert_Diff(float nl
, float *n
, float *v
, float darkness
)
752 /* nl = dot product between surface normal and light vector */
756 /* nv = dot product between surface normal and view vector */
757 nv
= n
[0]*v
[0]+n
[1]*v
[1]+n
[2]*v
[2];
761 if (darkness
<= 1.0f
)
762 i
= nl
* pow(MAX2(nv
*nl
, 0.1f
), (darkness
- 1.0f
) ); /*The Real model*/
764 i
= nl
* pow( (1.001f
- nv
), (darkness
- 1.0f
) ); /*Nvidia model*/
769 static float Fresnel_Diff(float *vn
, float *lv
, float *view
, float fac_i
, float fac
)
771 return fresnel_fac(lv
, vn
, fac_i
, fac
);
774 /* --------------------------------------------- */
775 /* also called from texture.c */
776 void calc_R_ref(ShadeInput
*shi
)
780 /* shi->vn dot shi->view */
781 i
= -2*(shi
->vn
[0]*shi
->view
[0]+shi
->vn
[1]*shi
->view
[1]+shi
->vn
[2]*shi
->view
[2]);
783 shi
->ref
[0]= (shi
->view
[0]+i
*shi
->vn
[0]);
784 shi
->ref
[1]= (shi
->view
[1]+i
*shi
->vn
[1]);
785 shi
->ref
[2]= (shi
->view
[2]+i
*shi
->vn
[2]);
787 if(shi
->vlr
->flag
& R_SMOOTH
) {
788 i
= -2*( (shi
->vn
[0]+shi
->dxno
[0])*(shi
->view
[0]+shi
->dxview
) +
789 (shi
->vn
[1]+shi
->dxno
[1])*shi
->view
[1]+ (shi
->vn
[2]+shi
->dxno
[2])*shi
->view
[2] );
791 shi
->dxref
[0]= shi
->ref
[0]- ( shi
->view
[0]+shi
->dxview
+i
*(shi
->vn
[0]+shi
->dxno
[0]));
792 shi
->dxref
[1]= shi
->ref
[1]- (shi
->view
[1]+ i
*(shi
->vn
[1]+shi
->dxno
[1]));
793 shi
->dxref
[2]= shi
->ref
[2]- (shi
->view
[2]+ i
*(shi
->vn
[2]+shi
->dxno
[2]));
795 i
= -2*( (shi
->vn
[0]+shi
->dyno
[0])*shi
->view
[0]+
796 (shi
->vn
[1]+shi
->dyno
[1])*(shi
->view
[1]+shi
->dyview
)+ (shi
->vn
[2]+shi
->dyno
[2])*shi
->view
[2] );
798 shi
->dyref
[0]= shi
->ref
[0]- (shi
->view
[0]+ i
*(shi
->vn
[0]+shi
->dyno
[0]));
799 shi
->dyref
[1]= shi
->ref
[1]- (shi
->view
[1]+shi
->dyview
+i
*(shi
->vn
[1]+shi
->dyno
[1]));
800 shi
->dyref
[2]= shi
->ref
[2]- (shi
->view
[2]+ i
*(shi
->vn
[2]+shi
->dyno
[2]));
805 i
= -2*( shi
->vn
[0]*(shi
->view
[0]+shi
->dxview
) +
806 shi
->vn
[1]*shi
->view
[1]+ shi
->vn
[2]*shi
->view
[2] );
808 shi
->dxref
[0]= shi
->ref
[0]- (shi
->view
[0]+shi
->dxview
+i
*shi
->vn
[0]);
809 shi
->dxref
[1]= shi
->ref
[1]- (shi
->view
[1]+ i
*shi
->vn
[1]);
810 shi
->dxref
[2]= shi
->ref
[2]- (shi
->view
[2]+ i
*shi
->vn
[2]);
812 i
= -2*( shi
->vn
[0]*shi
->view
[0]+
813 shi
->vn
[1]*(shi
->view
[1]+shi
->dyview
)+ shi
->vn
[2]*shi
->view
[2] );
815 shi
->dyref
[0]= shi
->ref
[0]- (shi
->view
[0]+ i
*shi
->vn
[0]);
816 shi
->dyref
[1]= shi
->ref
[1]- (shi
->view
[1]+shi
->dyview
+i
*shi
->vn
[1]);
817 shi
->dyref
[2]= shi
->ref
[2]- (shi
->view
[2]+ i
*shi
->vn
[2]);
823 /* called from ray.c */
824 void shade_color(ShadeInput
*shi
, ShadeResult
*shr
)
826 Material
*ma
= shi
->mat
;
828 if(ma
->mode
& (MA_VERTEXCOLP
|MA_FACETEXTURE
)) {
829 shi
->r
= shi
->vcol
[0];
830 shi
->g
= shi
->vcol
[1];
831 shi
->b
= shi
->vcol
[2];
832 if(ma
->mode
& (MA_FACETEXTURE_ALPHA
))
833 shi
->alpha
= shi
->vcol
[3];
837 do_material_tex(shi
);
839 if(ma
->fresnel_tra
!=0.0f
)
840 shi
->alpha
*= fresnel_fac(shi
->view
, shi
->vn
, ma
->fresnel_tra_i
, ma
->fresnel_tra
);
842 shr
->diff
[0]= shi
->r
;
843 shr
->diff
[1]= shi
->g
;
844 shr
->diff
[2]= shi
->b
;
845 shr
->alpha
= shi
->alpha
;
848 /* ramp for at end of shade */
849 static void ramp_diffuse_result(float *diff
, ShadeInput
*shi
)
851 Material
*ma
= shi
->mat
;
855 if(ma
->rampin_col
==MA_RAMP_IN_RESULT
) {
857 fac
= 0.3*diff
[0] + 0.58*diff
[1] + 0.12*diff
[2];
858 do_colorband(ma
->ramp_col
, fac
, col
);
860 /* blending method */
861 fac
= col
[3]*ma
->rampfac_col
;
863 ramp_blend(ma
->rampblend_col
, diff
, diff
+1, diff
+2, fac
, col
);
868 /* r,g,b denote energy, ramp is used with different values to make new material color */
869 static void add_to_diffuse(float *diff
, ShadeInput
*shi
, float is
, float r
, float g
, float b
)
871 Material
*ma
= shi
->mat
;
872 float col
[4], colt
[3], fac
=0;
874 if(ma
->ramp_col
&& (ma
->mode
& MA_RAMP_COL
)) {
876 /* MA_RAMP_IN_RESULT is exceptional */
877 if(ma
->rampin_col
==MA_RAMP_IN_RESULT
) {
879 diff
[0] += r
* shi
->r
;
880 diff
[1] += g
* shi
->g
;
881 diff
[2] += b
* shi
->b
;
885 switch(ma
->rampin_col
) {
886 case MA_RAMP_IN_ENERGY
:
887 fac
= 0.3*r
+ 0.58*g
+ 0.12*b
;
889 case MA_RAMP_IN_SHADER
:
893 fac
= shi
->view
[0]*shi
->vn
[0] + shi
->view
[1]*shi
->vn
[1] + shi
->view
[2]*shi
->vn
[2];
897 do_colorband(ma
->ramp_col
, fac
, col
);
899 /* blending method */
900 fac
= col
[3]*ma
->rampfac_col
;
905 ramp_blend(ma
->rampblend_col
, colt
, colt
+1, colt
+2, fac
, col
);
908 diff
[0] += r
* colt
[0];
909 diff
[1] += g
* colt
[1];
910 diff
[2] += b
* colt
[2];
914 diff
[0] += r
* shi
->r
;
915 diff
[1] += g
* shi
->g
;
916 diff
[2] += b
* shi
->b
;
920 static void ramp_spec_result(float *specr
, float *specg
, float *specb
, ShadeInput
*shi
)
922 Material
*ma
= shi
->mat
;
926 if(ma
->ramp_spec
&& (ma
->rampin_spec
==MA_RAMP_IN_RESULT
)) {
927 fac
= 0.3*(*specr
) + 0.58*(*specg
) + 0.12*(*specb
);
928 do_colorband(ma
->ramp_spec
, fac
, col
);
930 /* blending method */
931 fac
= col
[3]*ma
->rampfac_spec
;
933 ramp_blend(ma
->rampblend_spec
, specr
, specg
, specb
, fac
, col
);
938 /* is = dot product shade, t = spec energy */
939 static void do_specular_ramp(ShadeInput
*shi
, float is
, float t
, float *spec
)
941 Material
*ma
= shi
->mat
;
949 /* MA_RAMP_IN_RESULT is exception */
950 if(ma
->ramp_spec
&& (ma
->rampin_spec
!=MA_RAMP_IN_RESULT
)) {
953 switch(ma
->rampin_spec
) {
954 case MA_RAMP_IN_ENERGY
:
957 case MA_RAMP_IN_SHADER
:
961 fac
= shi
->view
[0]*shi
->vn
[0] + shi
->view
[1]*shi
->vn
[1] + shi
->view
[2]*shi
->vn
[2];
965 do_colorband(ma
->ramp_spec
, fac
, col
);
967 /* blending method */
968 fac
= col
[3]*ma
->rampfac_spec
;
970 ramp_blend(ma
->rampblend_spec
, spec
, spec
+1, spec
+2, fac
, col
);
974 /* pure AO, check for raytrace and world should have been done */
975 void ambient_occlusion(ShadeInput
*shi
)
978 if((R
.r
.mode
& R_RAYTRACE
) && shi
->mat
->amb
!=0.0f
)
979 ray_ao(shi
, shi
->ao
);
981 shi
->ao
[0]= shi
->ao
[1]= shi
->ao
[2]= 1.0f
;
985 /* wrld mode was checked for */
986 void ambient_occlusion_to_diffuse(ShadeInput
*shi
, float *diff
)
989 if((R
.r
.mode
& R_RAYTRACE
) && shi
->mat
->amb
!=0.0f
) {
990 float f
= R
.wrld
.aoenergy
*shi
->mat
->amb
;
992 if (R
.wrld
.aomix
==WO_AOADDSUB
) {
993 diff
[0] = 2.0f
*shi
->ao
[0]-1.0f
;
994 diff
[1] = 2.0f
*shi
->ao
[1]-1.0f
;
995 diff
[2] = 2.0f
*shi
->ao
[2]-1.0f
;
997 else if (R
.wrld
.aomix
==WO_AOSUB
) {
998 diff
[0] = shi
->ao
[0]-1.0f
;
999 diff
[1] = shi
->ao
[1]-1.0f
;
1000 diff
[2] = shi
->ao
[2]-1.0f
;
1003 VECCOPY(diff
, shi
->ao
);
1009 diff
[0]= diff
[1]= diff
[2]= 0.0f
;
1012 /* result written in shadfac */
1013 void lamp_get_shadow(LampRen
*lar
, ShadeInput
*shi
, float inp
, float *shadfac
, int do_real
)
1015 LampShadowSubSample
*lss
= &(lar
->shadsamp
[shi
->thread
].s
[shi
->sample
]);
1017 if(do_real
|| lss
->samplenr
!=shi
->samplenr
) {
1019 shadfac
[0]= shadfac
[1]= shadfac
[2]= shadfac
[3]= 1.0f
;
1022 if(lar
->buftype
==LA_SHADBUF_IRREGULAR
)
1023 shadfac
[3]= ISB_getshadow(shi
, lar
->shb
);
1025 shadfac
[3] = testshadowbuf(lar
->shb
, shi
->co
, shi
->dxco
, shi
->dyco
, inp
);
1027 else if(lar
->mode
& LA_SHAD_RAY
) {
1028 ray_shadow(shi
, lar
, shadfac
);
1032 QUATCOPY(lss
->shadfac
, shadfac
);
1033 lss
->samplenr
= shi
->samplenr
;
1037 QUATCOPY(shadfac
, lss
->shadfac
);
1041 /* lampdistance and spot angle, writes in lv and dist */
1042 float lamp_get_visibility(LampRen
*lar
, float *co
, float *lv
, float *dist
)
1044 if(lar
->type
==LA_SUN
|| lar
->type
==LA_HEMI
) {
1046 VECCOPY(lv
, lar
->vec
);
1050 float visifac
= 1.0f
, t
;
1052 VECSUB(lv
, co
, lar
->co
);
1053 *dist
= sqrt( INPR(lv
, lv
));
1057 /* area type has no quad or sphere option */
1058 if(lar
->type
==LA_AREA
) {
1059 /* area is single sided */
1060 if(INPR(lv
, lar
->vec
) > 0.0f
)
1066 switch(lar
->falloff_type
)
1068 case LA_FALLOFF_CONSTANT
:
1071 case LA_FALLOFF_INVLINEAR
:
1072 visifac
= lar
->dist
/(lar
->dist
+ dist
[0]);
1074 case LA_FALLOFF_INVSQUARE
:
1075 visifac
= lar
->dist
/ (lar
->dist
+ dist
[0]*dist
[0]);
1077 case LA_FALLOFF_SLIDERS
:
1079 visifac
= lar
->dist
/(lar
->dist
+lar
->ld1
*dist
[0]);
1081 visifac
*= lar
->distkw
/(lar
->distkw
+lar
->ld2
*dist
[0]*dist
[0]);
1083 case LA_FALLOFF_CURVE
:
1084 visifac
= curvemapping_evaluateF(lar
->curfalloff
, 0, dist
[0]/lar
->dist
);
1088 if(lar
->mode
& LA_SPHERE
) {
1089 float t
= lar
->dist
- dist
[0];
1093 visifac
*= t
/lar
->dist
;
1096 if(visifac
> 0.0f
) {
1097 if(lar
->type
==LA_SPOT
) {
1100 if(lar
->mode
& LA_SQUARE
) {
1101 if(lv
[0]*lar
->vec
[0]+lv
[1]*lar
->vec
[1]+lv
[2]*lar
->vec
[2]>0.0f
) {
1104 /* rotate view to lampspace */
1106 MTC_Mat3MulVecfl(lar
->imat
, lvrot
);
1108 x
= MAX2(fabs(lvrot
[0]/lvrot
[2]) , fabs(lvrot
[1]/lvrot
[2]));
1109 /* 1.0f/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
1111 inpr
= 1.0f
/(sqrt(1.0f
+x
*x
));
1116 inpr
= lv
[0]*lar
->vec
[0]+lv
[1]*lar
->vec
[1]+lv
[2]*lar
->vec
[2];
1124 if(t
<lar
->spotbl
&& lar
->spotbl
!=0.0f
) {
1126 float i
= t
/lar
->spotbl
;
1128 inpr
*= (3.0f
*t
-2.0f
*t
*i
);
1135 if (visifac
<= 0.001) visifac
= 0.0f
;
1140 /* function returns raw diff, spec and full shadowed diff in the 'shad' pass */
1141 static void shade_one_light(LampRen
*lar
, ShadeInput
*shi
, ShadeResult
*shr
, int passflag
)
1143 Material
*ma
= shi
->mat
;
1144 VlakRen
*vlr
= shi
->vlr
;
1145 float lv
[3], lampdist
, lacol
[3], shadfac
[4];
1146 float i
, is
, i_noshad
, inp
, *vn
, *view
, vnor
[3], phongcorr
=1.0f
;
1152 /* optimisation, don't render fully black lamps */
1153 if (!(lar
->mode
& LA_TEXTURE
) && (lar
->r
+ lar
->g
+ lar
->b
== 0.0f
))
1156 if (lar
->energy
== 0.0) return;
1158 /* lampdist, spot angle, area side, ... */
1159 visifac
= lamp_get_visibility(lar
, shi
->co
, lv
, &lampdist
);
1163 if(lar
->type
==LA_SPOT
) {
1164 if(lar
->mode
& LA_OSATEX
) {
1165 shi
->osatex
= 1; /* signal for multitex() */
1167 shi
->dxlv
[0]= lv
[0] - (shi
->co
[0]-lar
->co
[0]+shi
->dxco
[0])/lampdist
;
1168 shi
->dxlv
[1]= lv
[1] - (shi
->co
[1]-lar
->co
[1]+shi
->dxco
[1])/lampdist
;
1169 shi
->dxlv
[2]= lv
[2] - (shi
->co
[2]-lar
->co
[2]+shi
->dxco
[2])/lampdist
;
1171 shi
->dylv
[0]= lv
[0] - (shi
->co
[0]-lar
->co
[0]+shi
->dyco
[0])/lampdist
;
1172 shi
->dylv
[1]= lv
[1] - (shi
->co
[1]-lar
->co
[1]+shi
->dyco
[1])/lampdist
;
1173 shi
->dylv
[2]= lv
[2] - (shi
->co
[2]-lar
->co
[2]+shi
->dyco
[2])/lampdist
;
1177 /* lamp color texture */
1182 if(lar
->mode
& LA_TEXTURE
) do_lamp_tex(lar
, lv
, shi
, lacol
);
1184 /* tangent case; calculate fake face normal, aligned with lampvector */
1185 /* note, vnor==vn is used as tangent trigger for buffer shadow */
1186 if(vlr
->flag
& R_TANGENT
) {
1188 Crossf(cross
, lv
, vn
);
1189 Crossf(vnor
, cross
, vn
);
1190 vnor
[0]= -vnor
[0];vnor
[1]= -vnor
[1];vnor
[2]= -vnor
[2];
1193 else if (ma
->mode
& MA_TANGENT_V
) {
1195 Crossf(cross
, lv
, shi
->tang
);
1196 Crossf(vnor
, cross
, shi
->tang
);
1197 vnor
[0]= -vnor
[0];vnor
[1]= -vnor
[1];vnor
[2]= -vnor
[2];
1201 /* dot product and reflectivity */
1202 /* inp = dotproduct, is = shader result, i = lamp energy (with shadow), i_noshad = i without shadow */
1203 inp
= vn
[0]*lv
[0] + vn
[1]*lv
[1] + vn
[2]*lv
[2];
1205 /* phong threshold to prevent backfacing faces having artefacts on ray shadow (terminator problem) */
1206 /* this complex construction screams for a nicer implementation! (ton) */
1207 if(R
.r
.mode
& R_SHADOW
) {
1208 if(ma
->mode
& MA_SHADOW
) {
1209 if(lar
->type
==LA_HEMI
);
1210 else if((ma
->mode
& MA_RAYBIAS
) && (lar
->mode
& LA_SHAD_RAY
) && (vlr
->flag
& R_SMOOTH
)) {
1211 float thresh
= vlr
->ob
->smoothresh
;
1213 phongcorr
= (inp
-thresh
)/(inp
*(1.0f
-thresh
));
1217 else if(ma
->sbias
!=0.0f
&& ((lar
->mode
& LA_SHAD_RAY
) || lar
->shb
)) {
1219 phongcorr
= (inp
-ma
->sbias
)/(inp
*(1.0f
-ma
->sbias
));
1226 /* diffuse shaders */
1227 if(lar
->mode
& LA_NO_DIFF
) {
1228 is
= 0.0f
; // skip shaders
1230 else if(lar
->type
==LA_HEMI
) {
1231 is
= 0.5f
*inp
+ 0.5f
;
1235 if(lar
->type
==LA_AREA
)
1236 inp
= area_lamp_energy(shi
->co
, vn
, lar
);
1238 /* diffuse shaders (oren nayer gets inp from area light) */
1239 if(ma
->diff_shader
==MA_DIFF_ORENNAYAR
) is
= OrenNayar_Diff(inp
, vn
, lv
, view
, ma
->roughness
);
1240 else if(ma
->diff_shader
==MA_DIFF_TOON
) is
= Toon_Diff(vn
, lv
, view
, ma
->param
[0], ma
->param
[1]);
1241 else if(ma
->diff_shader
==MA_DIFF_MINNAERT
) is
= Minnaert_Diff(inp
, vn
, view
, ma
->darkness
);
1242 else if(ma
->diff_shader
==MA_DIFF_FRESNEL
) is
= Fresnel_Diff(vn
, lv
, view
, ma
->param
[0], ma
->param
[1]);
1243 else is
= inp
; // Lambert
1246 /* 'is' is diffuse */
1247 if((ma
->shade_flag
& MA_CUBIC
) && is
>0.0f
&& is
<1.0f
)
1248 is
= 3.0*is
*is
- 2.0*is
*is
*is
; // nicer termination of shades
1253 i
*= visifac
*shi
->refl
;
1257 vn
= shi
->vn
; // bring back original vector, we use special specular shaders for tangent
1258 if(ma
->mode
& MA_TANGENT_V
)
1261 /* init transp shadow */
1262 shadfac
[0]= shadfac
[1]= shadfac
[2]= shadfac
[3]= 1.0f
;
1264 /* shadow and spec, (visifac==0 outside spot) */
1267 if((R
.r
.mode
& R_SHADOW
)) {
1268 if(ma
->mode
& MA_SHADOW
) {
1269 if(lar
->shb
|| (lar
->mode
& LA_SHAD_RAY
)) {
1271 if(vn
==vnor
) /* tangent trigger */
1272 lamp_get_shadow(lar
, shi
, INPR(shi
->vn
, lv
), shadfac
, shi
->depth
);
1274 lamp_get_shadow(lar
, shi
, inp
, shadfac
, shi
->depth
);
1276 /* warning, here it skips the loop */
1277 if((lar
->mode
& LA_ONLYSHADOW
) && i
>0.0) {
1279 shadfac
[3]= i
*lar
->energy
*(1.0f
-shadfac
[3]);
1280 shr
->shad
[0] -= shadfac
[3]*shi
->r
;
1281 shr
->shad
[1] -= shadfac
[3]*shi
->g
;
1282 shr
->shad
[2] -= shadfac
[3]*shi
->b
;
1284 shr
->spec
[0] -= shadfac
[3]*shi
->specr
;
1285 shr
->spec
[1] -= shadfac
[3]*shi
->specg
;
1286 shr
->spec
[2] -= shadfac
[3]*shi
->specb
;
1296 /* in case 'no diffuse' we still do most calculus, spec can be in shadow.*/
1297 if(!(lar
->mode
& LA_NO_DIFF
)) {
1299 if(ma
->mode
& MA_SHADOW_TRA
)
1300 add_to_diffuse(shr
->shad
, shi
, is
, i
*shadfac
[0]*lacol
[0], i
*shadfac
[1]*lacol
[1], i
*shadfac
[2]*lacol
[2]);
1302 add_to_diffuse(shr
->shad
, shi
, is
, i
*lacol
[0], i
*lacol
[1], i
*lacol
[2]);
1305 if(passflag
& (SCE_PASS_DIFFUSE
|SCE_PASS_SHADOW
)) {
1306 if(ma
->mode
& MA_SHADOW_TRA
)
1307 add_to_diffuse(shr
->diff
, shi
, is
, i_noshad
*shadfac
[0]*lacol
[0], i_noshad
*shadfac
[1]*lacol
[1], i_noshad
*shadfac
[2]*lacol
[2]);
1309 add_to_diffuse(shr
->diff
, shi
, is
, i_noshad
*lacol
[0], i_noshad
*lacol
[1], i_noshad
*lacol
[2]);
1312 VECCOPY(shr
->diff
, shr
->shad
);
1317 if(shadfac
[3]>0.0f
&& shi
->spec
!=0.0f
&& !(lar
->mode
& LA_NO_SPEC
) && !(lar
->mode
& LA_ONLYSHADOW
)) {
1319 if(!(passflag
& (SCE_PASS_COMBINED
|SCE_PASS_SPEC
)));
1320 else if(lar
->type
==LA_HEMI
) {
1322 /* hemi uses no spec shaders (yet) */
1330 t
= vn
[0]*lv
[0]+vn
[1]*lv
[1]+vn
[2]*lv
[2];
1332 if(lar
->type
==LA_HEMI
) {
1336 t
= shadfac
[3]*shi
->spec
*spec(t
, shi
->har
);
1338 shr
->spec
[0]+= t
*(lacol
[0] * shi
->specr
);
1339 shr
->spec
[1]+= t
*(lacol
[1] * shi
->specg
);
1340 shr
->spec
[2]+= t
*(lacol
[2] * shi
->specb
);
1343 /* specular shaders */
1346 if(ma
->spec_shader
==MA_SPEC_PHONG
)
1347 specfac
= Phong_Spec(vn
, lv
, view
, shi
->har
, (vlr
->flag
& R_TANGENT
) || (ma
->mode
& MA_TANGENT_V
));
1348 else if(ma
->spec_shader
==MA_SPEC_COOKTORR
)
1349 specfac
= CookTorr_Spec(vn
, lv
, view
, shi
->har
, (vlr
->flag
& R_TANGENT
) || (ma
->mode
& MA_TANGENT_V
));
1350 else if(ma
->spec_shader
==MA_SPEC_BLINN
)
1351 specfac
= Blinn_Spec(vn
, lv
, view
, ma
->refrac
, (float)shi
->har
, (vlr
->flag
& R_TANGENT
) || (ma
->mode
& MA_TANGENT_V
));
1352 else if(ma
->spec_shader
==MA_SPEC_WARDISO
)
1353 specfac
= WardIso_Spec( vn
, lv
, view
, ma
->rms
, (vlr
->flag
& R_TANGENT
) || (ma
->mode
& MA_TANGENT_V
));
1355 specfac
= Toon_Spec(vn
, lv
, view
, ma
->param
[2], ma
->param
[3], (vlr
->flag
& R_TANGENT
) || (ma
->mode
& MA_TANGENT_V
));
1357 /* area lamp correction */
1358 if(lar
->type
==LA_AREA
) specfac
*= inp
;
1360 t
= shadfac
[3]*shi
->spec
*visifac
*specfac
;
1362 if(ma
->mode
& MA_RAMP_SPEC
) {
1364 do_specular_ramp(shi
, specfac
, t
, spec
);
1365 shr
->spec
[0]+= t
*(lacol
[0] * spec
[0]);
1366 shr
->spec
[1]+= t
*(lacol
[1] * spec
[1]);
1367 shr
->spec
[2]+= t
*(lacol
[2] * spec
[2]);
1370 shr
->spec
[0]+= t
*(lacol
[0] * shi
->specr
);
1371 shr
->spec
[1]+= t
*(lacol
[1] * shi
->specg
);
1372 shr
->spec
[2]+= t
*(lacol
[2] * shi
->specb
);
1379 static void shade_lamp_loop_only_shadow(ShadeInput
*shi
, ShadeResult
*shr
)
1382 if(R
.r
.mode
& R_SHADOW
) {
1387 float *vn
, *view
, shadfac
[4];
1388 float ir
, accum
, visifac
, lampdist
;
1395 lights
= get_lights(shi
);
1396 for(go
=lights
->first
; go
; go
= go
->next
) {
1398 if(lar
==NULL
) continue;
1400 /* yafray: ignore shading by photonlights, not used in Blender */
1401 if (lar
->type
==LA_YF_PHOTON
) continue;
1403 if(lar
->mode
& LA_LAYER
) if((lar
->lay
& shi
->vlr
->lay
)==0) continue;
1404 if((lar
->lay
& shi
->lay
)==0) continue;
1406 if(lar
->shb
|| (lar
->mode
& LA_SHAD_RAY
)) {
1407 visifac
= lamp_get_visibility(lar
, shi
->co
, lv
, &lampdist
);
1408 if(visifac
<= 0.0f
) {
1413 inpr
= INPR(shi
->vn
, lv
);
1419 lamp_get_shadow(lar
, shi
, inpr
, shadfac
, shi
->depth
);
1422 accum
+= (1.0f
-visifac
) + (visifac
)*shadfac
[3];
1427 shr
->alpha
= (shi
->mat
->alpha
)*(1.0f
-accum
);
1429 else shr
->alpha
= shi
->mat
->alpha
;
1432 /* quite disputable this... also note it doesn't mirror-raytrace */
1433 if((R
.wrld
.mode
& WO_AMB_OCC
) && shi
->amb
!=0.0f
) {
1436 f
= 1.0f
- shi
->ao
[0];
1437 f
= R
.wrld
.aoenergy
*f
*shi
->amb
;
1439 if(R
.wrld
.aomix
==WO_AOADD
) {
1443 else if(R
.wrld
.aomix
==WO_AOSUB
) {
1453 static void wrld_exposure_correct(float *diff
)
1455 diff
[0]= R
.wrld
.linfac
*(1.0f
-exp( diff
[0]*R
.wrld
.logfac
) );
1456 diff
[1]= R
.wrld
.linfac
*(1.0f
-exp( diff
[1]*R
.wrld
.logfac
) );
1457 diff
[2]= R
.wrld
.linfac
*(1.0f
-exp( diff
[2]*R
.wrld
.logfac
) );
1460 void shade_lamp_loop(ShadeInput
*shi
, ShadeResult
*shr
)
1462 Material
*ma
= shi
->mat
;
1463 VlakRen
*vlr
= shi
->vlr
;
1464 int passflag
= shi
->passflag
;
1466 memset(shr
, 0, sizeof(ShadeResult
));
1469 if(ma
->mode
& MA_ONLYSHADOW
) {
1470 shade_lamp_loop_only_shadow(shi
, shr
);
1474 /* envmap hack, always reset */
1475 shi
->refcol
[0]= shi
->refcol
[1]= shi
->refcol
[2]= shi
->refcol
[3]= 0.0f
;
1477 /* material color itself */
1478 if(passflag
& (SCE_PASS_COMBINED
|SCE_PASS_RGBA
)) {
1479 if(ma
->mode
& (MA_VERTEXCOLP
|MA_FACETEXTURE
)) {
1480 shi
->r
= shi
->vcol
[0];
1481 shi
->g
= shi
->vcol
[1];
1482 shi
->b
= shi
->vcol
[2];
1483 if(ma
->mode
& (MA_FACETEXTURE_ALPHA
))
1484 shi
->alpha
= shi
->vcol
[3];
1487 do_material_tex(shi
);
1489 shr
->col
[0]= shi
->r
*shi
->alpha
;
1490 shr
->col
[1]= shi
->g
*shi
->alpha
;
1491 shr
->col
[2]= shi
->b
*shi
->alpha
;
1492 shr
->col
[3]= shi
->alpha
;
1495 if(ma
->mode
& MA_SHLESS
) {
1496 shr
->combined
[0]= shi
->r
;
1497 shr
->combined
[1]= shi
->g
;
1498 shr
->combined
[2]= shi
->b
;
1499 shr
->alpha
= shi
->alpha
;
1503 if( (ma
->mode
& (MA_VERTEXCOL
|MA_VERTEXCOLP
))== MA_VERTEXCOL
) { // vertexcolor light
1504 shr
->diff
[0]= shi
->r
*(shi
->emit
+shi
->vcol
[0]);
1505 shr
->diff
[1]= shi
->g
*(shi
->emit
+shi
->vcol
[1]);
1506 shr
->diff
[2]= shi
->b
*(shi
->emit
+shi
->vcol
[2]);
1509 shr
->diff
[0]= shi
->r
*shi
->emit
;
1510 shr
->diff
[1]= shi
->g
*shi
->emit
;
1511 shr
->diff
[2]= shi
->b
*shi
->emit
;
1513 VECCOPY(shr
->shad
, shr
->diff
);
1516 if(R
.wrld
.mode
& WO_AMB_OCC
) {
1517 if(((passflag
& SCE_PASS_COMBINED
) && (shi
->combinedflag
& SCE_PASS_AO
))
1518 || (passflag
& SCE_PASS_AO
)) {
1519 /* AO was calculated for scanline already */
1521 ambient_occlusion(shi
);
1522 VECCOPY(shr
->ao
, shi
->ao
);
1527 if(passflag
& (SCE_PASS_COMBINED
|SCE_PASS_DIFFUSE
|SCE_PASS_SPEC
|SCE_PASS_SHADOW
)) {
1532 lights
= get_lights(shi
);
1533 for(go
=lights
->first
; go
; go
= go
->next
) {
1535 if(lar
==NULL
) continue;
1537 /* yafray: ignore shading by photonlights, not used in Blender */
1538 if (lar
->type
==LA_YF_PHOTON
) continue;
1540 /* test for lamp layer */
1541 if(lar
->mode
& LA_LAYER
) if((lar
->lay
& vlr
->lay
)==0) continue;
1542 if((lar
->lay
& shi
->lay
)==0) continue;
1544 /* accumulates in shr->diff and shr->spec and shr->shad (diffuse with shadow!) */
1545 shade_one_light(lar
, shi
, shr
, passflag
);
1548 /*this check is to prevent only shadow lamps from producing negative
1550 if (shr
->spec
[0] < 0) shr
->spec
[0] = 0;
1551 if (shr
->spec
[1] < 0) shr
->spec
[1] = 0;
1552 if (shr
->spec
[2] < 0) shr
->spec
[2] = 0;
1554 if (shr
->shad
[0] < 0) shr
->shad
[0] = 0;
1555 if (shr
->shad
[1] < 0) shr
->shad
[1] = 0;
1556 if (shr
->shad
[2] < 0) shr
->shad
[2] = 0;
1558 if(ma
->sss_flag
& MA_DIFF_SSS
) {
1559 float sss
[3], col
[3], texfac
= ma
->sss_texfac
;
1561 /* this will return false in the preprocess stage */
1562 if(sample_sss(&R
, ma
, shi
->co
, sss
)) {
1564 VECCOPY(col
, shr
->col
);
1566 else if(texfac
==1.0f
) {
1567 col
[0]= col
[1]= col
[2]= 1.0f
;
1570 col
[0]= pow(shr
->col
[0], 1.0f
-texfac
);
1571 col
[1]= pow(shr
->col
[1], 1.0f
-texfac
);
1572 col
[2]= pow(shr
->col
[2], 1.0f
-texfac
);
1575 shr
->diff
[0]= sss
[0]*col
[0];
1576 shr
->diff
[1]= sss
[1]*col
[1];
1577 shr
->diff
[2]= sss
[2]*col
[2];
1579 if(shi
->combinedflag
& SCE_PASS_SHADOW
) {
1580 shr
->shad
[0]= sss
[0]*col
[0];
1581 shr
->shad
[1]= sss
[1]*col
[1];
1582 shr
->shad
[2]= sss
[2]*col
[2];
1587 if(shi
->combinedflag
& SCE_PASS_SHADOW
)
1588 VECCOPY(shr
->combined
, shr
->shad
) /* note, no ';' ! */
1590 VECCOPY(shr
->combined
, shr
->diff
);
1592 /* calculate shadow pass, we use a multiplication mask */
1593 if(passflag
& SCE_PASS_SHADOW
) {
1594 if(shr
->diff
[0]!=0.0f
) shr
->shad
[0]= shr
->shad
[0]/shr
->diff
[0];
1595 if(shr
->diff
[1]!=0.0f
) shr
->shad
[1]= shr
->shad
[1]/shr
->diff
[1];
1596 if(shr
->diff
[2]!=0.0f
) shr
->shad
[2]= shr
->shad
[2]/shr
->diff
[2];
1599 /* exposure correction */
1600 if((R
.wrld
.exp
!=0.0f
|| R
.wrld
.range
!=1.0f
) && !R
.sss_points
) {
1601 wrld_exposure_correct(shr
->combined
); /* has no spec! */
1602 wrld_exposure_correct(shr
->spec
);
1606 /* alpha in end, spec can influence it */
1607 if(passflag
& (SCE_PASS_COMBINED
)) {
1608 if(ma
->fresnel_tra
!=0.0f
)
1609 shi
->alpha
*= fresnel_fac(shi
->view
, shi
->vn
, ma
->fresnel_tra_i
, ma
->fresnel_tra
);
1611 /* note: shi->mode! */
1612 if(shi
->mode
& (MA_ZTRA
|MA_RAYTRANSP
)) {
1613 if(shi
->spectra
!=0.0f
) {
1614 float t
= MAX3(shr
->spec
[0], shr
->spec
[1], shr
->spec
[2]);
1617 shi
->alpha
= (1.0f
-t
)*shi
->alpha
+t
;
1621 shr
->alpha
= shi
->alpha
;
1623 /* from now stuff everything in shr->combined: ambient, AO, radio, ramps, exposure */
1624 if(!(ma
->sss_flag
& MA_DIFF_SSS
) || !has_sss_tree(&R
, ma
)) {
1625 shr
->combined
[0]+= shi
->ambr
;
1626 shr
->combined
[1]+= shi
->ambg
;
1627 shr
->combined
[2]+= shi
->ambb
;
1629 if(shi
->combinedflag
& SCE_PASS_RADIO
) {
1630 shr
->combined
[0]+= shi
->r
*shi
->amb
*shi
->rad
[0];
1631 shr
->combined
[1]+= shi
->g
*shi
->amb
*shi
->rad
[1];
1632 shr
->combined
[2]+= shi
->b
*shi
->amb
*shi
->rad
[2];
1635 /* add AO in combined? */
1636 if(R
.wrld
.mode
& WO_AMB_OCC
) {
1637 if(shi
->combinedflag
& SCE_PASS_AO
) {
1639 ambient_occlusion_to_diffuse(shi
, aodiff
);
1641 shr
->combined
[0] += shi
->r
*aodiff
[0];
1642 shr
->combined
[1] += shi
->g
*aodiff
[1];
1643 shr
->combined
[2] += shi
->b
*aodiff
[2];
1647 if(ma
->mode
& MA_RAMP_COL
) ramp_diffuse_result(shr
->combined
, shi
);
1650 if(ma
->mode
& MA_RAMP_SPEC
) ramp_spec_result(shr
->spec
, shr
->spec
+1, shr
->spec
+2, shi
);
1652 /* refcol is for envmap only */
1653 if(shi
->refcol
[0]!=0.0f
) {
1656 result
[0]= shi
->mirr
*shi
->refcol
[1] + (1.0f
- shi
->mirr
*shi
->refcol
[0])*shr
->combined
[0];
1657 result
[1]= shi
->mirg
*shi
->refcol
[2] + (1.0f
- shi
->mirg
*shi
->refcol
[0])*shr
->combined
[1];
1658 result
[2]= shi
->mirb
*shi
->refcol
[3] + (1.0f
- shi
->mirb
*shi
->refcol
[0])*shr
->combined
[2];
1660 if(passflag
& SCE_PASS_REFLECT
)
1661 VECSUB(shr
->refl
, result
, shr
->combined
);
1663 if(shi
->combinedflag
& SCE_PASS_REFLECT
)
1664 VECCOPY(shr
->combined
, result
);
1669 if(shi
->combinedflag
& SCE_PASS_SPEC
)
1670 VECADD(shr
->combined
, shr
->combined
, shr
->spec
);
1672 shr
->combined
[3]= shr
->alpha
;