[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