[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [15716] branches/soc-2008-unclezeiv/source /blender/render/intern/source/shadeoutput.c: - readability enhancements for diffuse and specular shaders ( mostly used macros where possible, leading to clearer and more compact code )
Davide Vercelli
davide.vercelli at gmail.com
Wed Jul 23 19:23:56 CEST 2008
Revision: 15716
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=15716
Author: unclezeiv
Date: 2008-07-23 19:23:56 +0200 (Wed, 23 Jul 2008)
Log Message:
-----------
- readability enhancements for diffuse and specular shaders (mostly used macros where possible, leading to clearer and more compact code)
- a couple of slight optimizations (pre-computing parameters being used squared in many places, and anticipating a early out)
- a potential fix (parameter g in Blinn specularity could stay uncorrectly at 0.0 in some extreme corner cases)
Modified Paths:
--------------
branches/soc-2008-unclezeiv/source/blender/render/intern/source/shadeoutput.c
Modified: branches/soc-2008-unclezeiv/source/blender/render/intern/source/shadeoutput.c
===================================================================
--- branches/soc-2008-unclezeiv/source/blender/render/intern/source/shadeoutput.c 2008-07-23 16:59:54 UTC (rev 15715)
+++ branches/soc-2008-unclezeiv/source/blender/render/intern/source/shadeoutput.c 2008-07-23 17:23:56 UTC (rev 15716)
@@ -404,15 +404,13 @@
if(fac==0.0f) return 1.0f;
- t1= (view[0]*vn[0] + view[1]*vn[1] + view[2]*vn[2]);
- if(t1>0.0f) t2= 1.0f+t1;
+ t1= INPR(view, vn);
+ if(t1>0.0f) t2= 1.0f+t1;
else t2= 1.0f-t1;
t2= grad + (1.0f-grad)*pow(t2, fac);
- if(t2<0.0f) return 0.0f;
- else if(t2>1.0f) return 1.0f;
- return t2;
+ return CLAMPIS(t2, 0.0f, 1.0f);
}
static double saacos_d(double fac)
@@ -549,12 +547,10 @@
float h[3];
float rslt;
- h[0] = l[0] + v[0];
- h[1] = l[1] + v[1];
- h[2] = l[2] + v[2];
+ VECADD(h, v, l);
Normalize(h);
- rslt = h[0]*n[0] + h[1]*n[1] + h[2]*n[2];
+ rslt = INPR(h, n);
if(tangent) rslt= sasqrt(1.0f - rslt*rslt);
if( rslt > 0.0f ) rslt= spec(rslt, hard);
@@ -567,25 +563,20 @@
/* reduced cook torrance spec (for off-specular peak) */
static float CookTorr_Spec(float *n, float *l, float *v, int hard, int tangent)
{
- float i, nh, nv, h[3];
+ float nh, nv, h[3];
- h[0]= v[0]+l[0];
- h[1]= v[1]+l[1];
- h[2]= v[2]+l[2];
+ VECADD(h, v, l);
Normalize(h);
- nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2];
+ nh= INPR(n, h);
if(tangent) nh= sasqrt(1.0f - nh*nh);
else if(nh<0.0f) return 0.0f;
- nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2];
+ nv= INPR(n, v);
if(tangent) nv= sasqrt(1.0f - nv*nv);
else if(nv<0.0f) nv= 0.0f;
- i= spec(nh, hard);
-
- i= i/(0.1+nv);
- return i;
+ return spec(nh, hard)/(0.1+nv);
}
/* Blinn spec */
@@ -593,6 +584,7 @@
{
float i, nh, nv, nl, vh, h[3];
float a, b, c, g=0.0f, p, f, ang;
+ float num, den, pm, pp;
if(refrac < 1.0f) return 0.0f;
if(spec_power == 0.0f) return 0.0f;
@@ -602,38 +594,44 @@
spec_power= sqrt(1.0f/spec_power);
else spec_power= 10.0f/spec_power;
- h[0]= v[0]+l[0];
- h[1]= v[1]+l[1];
- h[2]= v[2]+l[2];
+ VECADD(h, v, l);
Normalize(h);
- nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */
+ /* Dot product between surface normal and half-way vector */
+ nh= INPR(n, h);
if(tangent) nh= sasqrt(1.0f - nh*nh);
else if(nh<0.0f) return 0.0f;
- nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */
+ /* Dot product between surface normal and view vector */
+ nv= INPR(n, v);
if(tangent) nv= sasqrt(1.0f - nv*nv);
if(nv<=0.01f) nv= 0.01f; /* hrms... */
- nl= n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */
+ /* Dot product between surface normal and light vector */
+ nl= INPR(n, l);
if(tangent) nl= sasqrt(1.0f - nl*nl);
if(nl<=0.01f) {
return 0.0f;
}
- vh= v[0]*h[0]+v[1]*h[1]+v[2]*h[2]; /* Dot product between view vector and half-way vector */
+ /* Dot product between view vector and half-way vector */
+ vh= INPR(v, h);
if(vh<=0.0f) vh= 0.01f;
a = 1.0f;
b = (2.0f*nh*nv)/vh;
c = (2.0f*nh*nl)/vh;
+
+ g= MIN3(a, b, c);
- if( a < b && a < c ) g = a;
- else if( b < a && b < c ) g = b;
- else if( c < a && c < b ) g = c;
-
p = sqrt( (double)((refrac * refrac)+(vh*vh)-1.0f) );
- 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))));
+ pm= p-vh;
+ pp= p+vh;
+ num= (vh*pp)-1.0f;
+ num*= num;
+ den= (vh*pm)+1.0f;
+ den*= den;
+ f = (pm*pm/(pp*pp)) * (1.0f + num/den);
ang = saacos(nh);
i= f * g * exp((double)(-(ang*ang) / (2.0f*spec_power*spec_power)));
@@ -649,12 +647,10 @@
float ang;
float rslt;
- h[0] = l[0] + v[0];
- h[1] = l[1] + v[1];
- h[2] = l[2] + v[2];
+ VECADD(h, v, l);
Normalize(h);
- rslt = h[0]*n[0] + h[1]*n[1] + h[2]*n[2];
+ rslt = INPR(h, n);
if(tangent) rslt = sasqrt(1.0f - rslt*rslt);
ang = saacos( rslt );
@@ -669,31 +665,32 @@
/* Ward isotropic gaussian spec */
static float WardIso_Spec( float *n, float *l, float *v, float rms, int tangent)
{
- float i, nh, nv, nl, h[3], angle, alpha;
+ float i, nh, nv, nl, h[3], angle, alpha_sq;
-
/* half-way vector */
- h[0] = l[0] + v[0];
- h[1] = l[1] + v[1];
- h[2] = l[2] + v[2];
+ VECADD(h, l, v);
Normalize(h);
- nh = n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */
+ /* Dot product between surface normal and half-way vector */
+ nh = INPR(n, h);
if(tangent) nh = sasqrt(1.0f - nh*nh);
if(nh<=0.0f) nh = 0.001f;
- nv = n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */
+ /* Dot product between surface normal and view vector */
+ nv = INPR(n, v);
if(tangent) nv = sasqrt(1.0f - nv*nv);
if(nv<=0.0f) nv = 0.001f;
- nl = n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */
+ /* Dot product between surface normal and light vector */
+ nl = INPR(n, l);
if(tangent) nl = sasqrt(1.0f - nl*nl);
if(nl<=0.0f) nl = 0.001f;
angle = tan(saacos(nh));
- alpha = MAX2(rms, 0.001f);
+ alpha_sq = MAX2(rms, 0.001f);
+ alpha_sq*= alpha_sq;
- i= nl * (1.0f/(4.0f*M_PI*alpha*alpha)) * (exp( -(angle*angle)/(alpha*alpha))/(sqrt(nv*nl)));
+ i= nl * (1.0f/(4.0f*M_PI*alpha_sq)) * (exp( -(angle*angle)/alpha_sq)/(sqrt(nv*nl)));
return i;
}
@@ -703,7 +700,7 @@
{
float rslt, ang;
- rslt = n[0]*l[0] + n[1]*l[1] + n[2]*l[2];
+ rslt = INPR(n, l);
ang = saacos( (double)(rslt) );
@@ -718,45 +715,46 @@
/* 'nl' is either dot product, or return value of area light */
/* in latter case, only last multiplication uses 'nl' */
-static float OrenNayar_Diff(float nl, float *n, float *l, float *v, float rough )
+static float OrenNayar_Diff(float nl, float *n, float *l, float *v, float rough_sq )
{
float i, nh, nv, vh, realnl, h[3];
float a, b, t, A, B;
float Lit_A, View_A, Lit_B[3], View_B[3];
+ if(nl<0.0f) return 0.0f; /* value from area light */
+
h[0]= v[0]+l[0];
h[1]= v[1]+l[1];
h[2]= v[2]+l[2];
Normalize(h);
- nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */
- if(nh<0.0f) nh = 0.0f;
+ /* Dot product between surface normal and half-way vector */
+ nh= INPR(n, h);
+ nh= MAX2(nh, 0.0f);
- nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */
- if(nv<=0.0f) nv= 0.0f;
+ /* Dot product between surface normal and view vector */
+ nv= INPR(n, v);
+ nv= MAX2(nv, 0.0f);
- realnl= n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */
+ /* Dot product between surface normal and light vector */
+ realnl= INPR(n, l);
if(realnl<=0.0f) return 0.0f;
- if(nl<0.0f) return 0.0f; /* value from area light */
- vh= v[0]*h[0]+v[1]*h[1]+v[2]*h[2]; /* Dot product between view vector and halfway vector */
- if(vh<=0.0f) vh= 0.0f;
+ /* Dot product between view vector and halfway vector */
+ vh= INPR(v, h);
+ vh= MAX2(vh, 0.0f);
Lit_A = saacos(realnl);
View_A = saacos( nv );
- Lit_B[0] = l[0] - (realnl * n[0]);
- Lit_B[1] = l[1] - (realnl * n[1]);
- Lit_B[2] = l[2] - (realnl * n[2]);
- Normalize( Lit_B );
+ VECADDFAC(Lit_B, l, n, -realnl);
+ Normalize(Lit_B);
- View_B[0] = v[0] - (nv * n[0]);
- View_B[1] = v[1] - (nv * n[1]);
- View_B[2] = v[2] - (nv * n[2]);
- Normalize( View_B );
+ VECADDFAC(View_B, v, n, -nv);
+ Normalize(View_B);
- t = Lit_B[0]*View_B[0] + Lit_B[1]*View_B[1] + Lit_B[2]*View_B[2];
- if( t < 0 ) t = 0;
+ t= INPR(Lit_B, View_B);
+ t= MAX2(t, 0.0f);
if( Lit_A > View_A ) {
a = Lit_A;
@@ -766,12 +764,12 @@
a = View_A;
b = Lit_A;
}
+ b*= 0.95f; /* prevent tangents from shooting t(rough * rough)o inf, 'nl' can be not a dot product here. */
+ /* overflow only happens with extreme size area light, and higher roughness */
- A = 1.0f - (0.5f * ((rough * rough) / ((rough * rough) + 0.33f)));
- B = 0.45f * ((rough * rough) / ((rough * rough) + 0.09f));
+ A = 1.0f - 0.5f * rough_sq / (rough_sq + 0.33f);
+ B = 0.45f * rough_sq / (rough_sq + 0.09f);
- b*= 0.95f; /* prevent tangens from shooting to inf, 'nl' can be not a dot product here. */
- /* overflow only happens with extreme size area light, and higher roughness */
i = nl * ( A + ( B * t * sin(a) * tan(b) ) );
return i;
@@ -780,7 +778,6 @@
/* Minnaert diffuse */
static float Minnaert_Diff(float nl, float *n, float *v, float darkness)
{
-
float i, nv;
/* nl = dot product between surface normal and light vector */
@@ -788,7 +785,7 @@
return 0.0f;
/* nv = dot product between surface normal and view vector */
- nv = n[0]*v[0]+n[1]*v[1]+n[2]*v[2];
+ nv = INPR(n, v);
if (nv < 0.0f)
nv = 0.0f;
@@ -1302,7 +1299,7 @@
inp= area_lamp_energy_multisample(lar, shi->co, vn);
/* diffuse shaders (oren nayer gets inp from area light) */
- if(ma->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff(inp, vn, lv, view, ma->roughness);
+ if(ma->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff(inp, vn, lv, view, ma->roughness * ma->roughness);
else if(ma->diff_shader==MA_DIFF_TOON) is= Toon_Diff(vn, lv, view, ma->param[0], ma->param[1]);
else if(ma->diff_shader==MA_DIFF_MINNAERT) is= Minnaert_Diff(inp, vn, view, ma->darkness);
else if(ma->diff_shader==MA_DIFF_FRESNEL) is= Fresnel_Diff(vn, lv, view, ma->param[0], ma->param[1]);
@@ -1924,7 +1921,7 @@
#ifdef LC_LATER /* we start by supporting only lambert */
/* diffuse shaders (oren nayer gets inp from area light) */
- if(ma->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff(inp, vn, lv, view, ma->roughness);
+ if(ma->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff(inp, vn, lv, view, ma->roughness * ma->roughness);
else if(ma->diff_shader==MA_DIFF_TOON) is= Toon_Diff(vn, lv, view, ma->param[0], ma->param[1]);
else if(ma->diff_shader==MA_DIFF_MINNAERT) is= Minnaert_Diff(inp, vn, view, ma->darkness);
else if(ma->diff_shader==MA_DIFF_FRESNEL) is= Fresnel_Diff(vn, lv, view, ma->param[0], ma->param[1]);
More information about the Bf-blender-cvs
mailing list