[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [15864] branches/soc-2008-unclezeiv/source /blender/render/intern/source: Added support for "Bias" a.k.a.

Davide Vercelli davide.vercelli at gmail.com
Tue Jul 29 13:53:44 CEST 2008


Revision: 15864
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=15864
Author:   unclezeiv
Date:     2008-07-29 13:53:43 +0200 (Tue, 29 Jul 2008)

Log Message:
-----------
Added support for "Bias" a.k.a. "Phong correction" a.k.a. terminator problem etc.

Also rationalized the code a bit, and optimized the Oren Nayar bounding.

Notes:
- I'm not currently bounding the bias for the specular component; I also have a suspect that the current code is wrong for the specular case in shade_lamp_loop (will look into it)
- bounding components is good as it potentially saves computations, but it can get expensive itself on the other hand; a thourough run-time analysis should be run to see if some of the bounding code is not worth calling

Modified Paths:
--------------
    branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c
    branches/soc-2008-unclezeiv/source/blender/render/intern/source/shadeoutput.c

Modified: branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c
===================================================================
--- branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c	2008-07-29 11:37:11 UTC (rev 15863)
+++ branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c	2008-07-29 11:53:43 UTC (rev 15864)
@@ -167,6 +167,17 @@
 #endif
 } LightcutsData;
 
+typedef struct SampleCoordInfo {
+	float tsm[3][3];        /* tangent space matrix */
+	float tspos[3];         /* sample position in tangent space */
+	float msm[3][3];        /* mirror direction space matrix */
+	float mspos[3];         /* sample position in mirror space */
+	float dtsm[3][3];       /* tangent space matrix pointing downwards */
+	float dtspos[3];
+	float phongcorr_thresh; /* sample threshold (terminator problem) */
+	short do_phongcorr;
+} SampleCoordInfo;
+
 #define VEC_LEN_SQ(v) (v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
 #define VECCOPYMUL(v1,v2,aS) {*(v1)= *(v2)*aS; *(v1+1)= *(v2+1)*aS; *(v1+2)= *(v2+2)*aS;}
 #define VECNEG(v) {*(v)=-*(v); *(v+1)=-*(v+1); *(v+2)=-*(v+2);}
@@ -1099,7 +1110,7 @@
 
 float spec(float inp, int hard);
 
-float bound_OrenNayar_Diff(float max_dot, float min_dot, float *n, float *v, float *tmin, float *tmax, float rough_sq)
+static float bound_OrenNayar_Diff(float max_dot, float min_dot, float *n, float *v, float *tmin, float *tmax, float rough_sq)
 {
 	float nv, t, A, B;
 	float View_B[3], lmin[3], lmax[3], mat[3][3];
@@ -1150,7 +1161,7 @@
 	return max_dot * (A + B * t * bound_sin_tan);
 }
 
-float bound_Toon_Diff(float min_ang, float size, float smooth)
+static float bound_Toon_Diff(float min_ang, float size, float smooth)
 {
 	float ang = saacos( (double)(min_ang) );
 
@@ -1159,7 +1170,7 @@
 	return 1.0f - ((ang - size) / smooth);
 }
 
-float bound_Minnaert_Diff(float max_dot, float *n, float *v, float darkness)
+static float bound_Minnaert_Diff(float max_dot, float *n, float *v, float darkness)
 {
 	float nv;
 	
@@ -1179,7 +1190,7 @@
 	return max_dot * pow(1.001f - nv, darkness - 1.0f);
 }
 
-float bound_Fresnel_Diff(float max_dot, float grad, float fac)
+static float bound_Fresnel_Diff(float max_dot, float grad, float fac)
 {
 	float t2;
 	
@@ -1194,60 +1205,64 @@
 	return CLAMPIS(t2, 0.0f, 1.0f);
 }
 
+static float get_cosine_bound_in_given_space(float sm[3][3], float *pos, float *min, float *max, short trasl)
+{
+	float tmin[3], tmax[3];
+	transform_aabb(sm, min, max, tmin, tmax);
+	if (trasl) {
+		VECADD(tmin, pos, tmin);
+		VECADD(tmax, pos, tmax);
+	}
+	return compute_cosine_bound(tmin, tmax);
+}
+
 /* error bound: material term */
 /* TODO: currently supporting only Phong specular */
-static float calc_material_eb(LightcutsCluster *clus, ShadeInput *shi, float tsm[3][3], float *tspos, float msm[3][3], float *mspos)
+static float calc_material_eb(LightcutsCluster *clus, ShadeInput *shi, SampleCoordInfo *sci)
 {
-	float tmin[3], tmax[3], eb_diff, eb_spec=0.0f, cb;
-	transform_aabb(tsm, clus->min, clus->max, tmin, tmax);
-	if (clus->type != CLUSTER_SUN) {
-		VECADD(tmin, tspos, tmin);
-		VECADD(tmax, tspos, tmax);
-	}
-	cb= compute_cosine_bound(tmin, tmax);
+	float maxb, eb_diff, eb_spec= 0.0f;
 	
+	maxb= get_cosine_bound_in_given_space(sci->tsm, sci->tspos, clus->min, clus->max, clus->type != CLUSTER_SUN);
+	
+	/*
+	 * TODO: if we add support for non shadow lamps, check should be:
+	 * (sci->do_phongcorr && (lar->mode & LA_SHAD_RAY)) 
+	 */
+	if (sci->do_phongcorr && maxb <= sci->phongcorr_thresh)
+		return 0.0f;
+	
 	/* TODO: potentially optimizable, the shader is always the same over a sample */
 	switch(shi->mat->diff_shader) {
 	case MA_DIFF_TOON:
-		eb_diff= bound_Toon_Diff(MAX2(cb, 0.0), shi->mat->param[0], shi->mat->param[1]);
+		eb_diff= bound_Toon_Diff(MAX2(maxb, 0.0), shi->mat->param[0], shi->mat->param[1]);
 		break;
 	case MA_DIFF_MINNAERT:
-		eb_diff= bound_Minnaert_Diff(MAX2(cb, 0.0), shi->vn, shi->view, shi->mat->darkness);
+		eb_diff= bound_Minnaert_Diff(MAX2(maxb, 0.0), shi->vn, shi->view, shi->mat->darkness);
 		break;
 	case MA_DIFF_FRESNEL:
-		eb_diff= bound_Fresnel_Diff(MAX2(cb, 0.0), shi->mat->param[0], shi->mat->param[1]);
+		eb_diff= bound_Fresnel_Diff(MAX2(maxb, 0.0), shi->mat->param[0], shi->mat->param[1]);
 		break;
 	case MA_DIFF_ORENNAYAR:
 		{
-			/* TODO: optim: tsmdwn is always the same over the sample */
-			float tsmdwn[3][3], tdmin[3], tdmax[3], minb;
-			VECCOPY(tsmdwn[0], tsm[1]);
-			VECCOPY(tsmdwn[1], tsm[0]);
-			VECCOPY(tsmdwn[2], tsm[2]);
-			VECNEG(tsmdwn[2]);
-			transform_aabb(tsmdwn, clus->min, clus->max, tdmin, tdmax);
-			if (clus->type != CLUSTER_SUN) {
-				VECADD(tdmin, tspos, tdmin);
-				VECADD(tdmax, tspos, tdmax);
-			}
-			minb= compute_cosine_bound(tdmin, tdmax);
-			eb_diff= bound_OrenNayar_Diff(MAX2(cb, 0.0f), MAX2(minb, 0.0f), shi->vn, shi->view, clus->min, clus->max, shi->mat->roughness * shi->mat->roughness);
+			float minb= -get_cosine_bound_in_given_space(sci->dtsm, sci->dtspos, clus->min, clus->max, clus->type != CLUSTER_SUN);
+			eb_diff= bound_OrenNayar_Diff(MAX2(maxb, 0.0f), MAX2(minb, 0.0f), shi->vn, shi->view, clus->min, clus->max, shi->mat->roughness * shi->mat->roughness);
 		}
 		break;
 	default:
-		eb_diff= MAX2(cb, 0.0) * shi->refl;
+		eb_diff= MAX2(maxb, 0.0) * shi->refl;
 	}
 	
+	if (sci->do_phongcorr) {
+		float phongcorr= (maxb - sci->phongcorr_thresh) / (maxb * (1.0f - sci->phongcorr_thresh));
+		eb_diff*= phongcorr;
+	}
+	
 	if (shi->mat->spec_shader==MA_SPEC_PHONG) {
-		transform_aabb(msm, clus->min, clus->max, tmin, tmax);
-		if (clus->type != CLUSTER_SUN) {
-			VECADD(tmin, mspos, tmin);
-			VECADD(tmax, mspos, tmax);
-		}
 		// t= shadfac[3]*shi->spec*visifac*specfac;
-		cb= compute_cosine_bound(tmin, tmax);
-		eb_spec= spec(MAX2(cb, 0.0), shi->har) * shi->spec;
+		maxb= get_cosine_bound_in_given_space(sci->msm, sci->mspos, clus->min, clus->max, clus->type != CLUSTER_SUN);
+		eb_spec= spec(MAX2(maxb, 0.0), shi->har) * shi->spec;
 	}
+	
 	return eb_diff + eb_spec;
 }
 
@@ -1341,10 +1356,7 @@
 	int used= 0;
 	int used_type[3]= {0, 0, 0};
 	float i, i_noshad, t;
-	float tsm[3][3]; /* tangent space matrix */
-	float msm[3][3]; /* mirror direction space matrix */
-	float tspos[3];
-	float mspos[3];
+	SampleCoordInfo sci;
 	float noropp[3];
 	float mirdir[3];
 	LightcutsCluster *array;
@@ -1370,13 +1382,22 @@
 	/* XXX: shi->vn seems to point inside the mesh, investigate; works inverted like this */
 	VECCOPY(noropp, shi->vn);
 	VECNEG(noropp);
-	get_axis_matrix(tsm, noropp);
+	get_axis_matrix(sci.tsm, noropp);
 	
 	/* get sample coordinates in tangent space */
-	VECCOPY(tspos, shi->co);
-	Mat3MulVecfl(tsm, tspos);
-	VECNEG(tspos);
+	VECCOPY(sci.tspos, shi->co);
+	Mat3MulVecfl(sci.tsm, sci.tspos);
+	VECNEG(sci.tspos);
 	
+	/* compute downwards tangent space matrix */
+	VECCOPY(sci.dtsm[0], sci.tsm[1]);
+	VECCOPY(sci.dtsm[1], sci.tsm[0]);
+	VECCOPY(sci.dtsm[2], sci.tsm[2]);
+	VECNEG(sci.dtsm[2]);
+	VECCOPY(sci.dtspos, shi->co);
+	Mat3MulVecfl(sci.dtsm, sci.dtspos);
+	VECNEG(sci.dtspos);
+	
 	/* create mirror direction space */
 	{
 		float nor2[3];
@@ -1386,11 +1407,21 @@
 		VecMulf(nor2, -2 * Inpf(mirdir, nor2));
 		VecAddf(mirdir, nor2, mirdir);
 		
-		get_axis_matrix(msm, mirdir);
-		VECCOPY(mspos, shi->co);
-		Mat3MulVecfl(msm, mspos);
-		VECNEG(mspos);
+		get_axis_matrix(sci.msm, mirdir);
+		VECCOPY(sci.mspos, shi->co);
+		Mat3MulVecfl(sci.msm, sci.mspos);
+		VECNEG(sci.mspos);
 	}
+	
+	if(shi->mat->mode & MA_SHADOW) {
+		sci.phongcorr_thresh= 0.0f;
+		if((shi->mat->mode & MA_RAYBIAS) && (shi->vlr->flag & R_SMOOTH))
+			sci.phongcorr_thresh= shi->obr->ob->smoothresh;
+		else if(shi->mat->sbias!=0.0f)
+			sci.phongcorr_thresh= shi->mat->sbias;
+		if (sci.phongcorr_thresh!=0.0f)
+			sci.do_phongcorr= 1;
+	}
 
 	cut_nodes= lcd->cut_nodes + shi->thread * lcd->cut_nodes_size;
 
@@ -1407,7 +1438,7 @@
 
 				root->id= tree->root;
 				root->type= clus->type;
-				root->error_bound= calc_geometric_eb(lcd, clus, shi->co) * calc_material_eb(clus, shi, tsm, tspos, msm, mspos);
+				root->error_bound= calc_geometric_eb(lcd, clus, shi->co) * calc_material_eb(clus, shi, &sci);
 #ifdef LIGHTCUTS_DEBUG
 				dbg_convert[tree->root]= 0;
 #endif
@@ -1476,8 +1507,10 @@
 					hinode->child1, hinode->child2);
 		}
 		if (cn_hinode->error_bound + FLT_EPSILON < cn_hinode->contr_factor) {
-			printf("troublesome node! at %d, %d (it=%d) (id=%4d): eb %7.5f < cf %7.5f, (%10.6f * 10^6)\n",
-					shi->xs, shi->ys, it, cn_hinode->id, cn_hinode->error_bound, cn_hinode->contr_factor, 1000000.0f * fabs(cn_hinode->error_bound - cn_hinode->contr_factor));
+			float error = 1000000.0f * fabs(cn_hinode->error_bound - cn_hinode->contr_factor);
+			if (error > 1.0f) /* greater than 10^-6 ! */
+				printf("troublesome node! at %d, %d (it=%d) (id=%4d): eb %7.5f < cf %7.5f, (%10.6f * 10^-6)\n",
+						shi->xs, shi->ys, it, cn_hinode->id, cn_hinode->error_bound, cn_hinode->contr_factor, error);
 			// break;
 		}
 
@@ -1522,7 +1555,7 @@
 			/* for the represented light we can reuse most calculations */
 			cn_rep->id= rep->id;
 			cn_rep->type= rep->type;
-			cn_rep->error_bound= calc_geometric_eb(lcd, rep, shi->co) * calc_material_eb(rep, shi, tsm, tspos, msm, mspos);
+			cn_rep->error_bound= calc_geometric_eb(lcd, rep, shi->co) * calc_material_eb(rep, shi, &sci);
 
 			if (cn_rep->error_bound > FLT_EPSILON) {
 				cn_rep->contr_factor= cn_hinode->contr_factor;
@@ -1554,7 +1587,7 @@
 			/* for the "unrepresented" light we have to compute stuff from scratch */
 			cn_unrep->id= unrep->id;
 			cn_unrep->type= unrep->type;
-			cn_unrep->error_bound= calc_geometric_eb(lcd, unrep, shi->co) * calc_material_eb(unrep, shi, tsm, tspos, msm, mspos);
+			cn_unrep->error_bound= calc_geometric_eb(lcd, unrep, shi->co) * calc_material_eb(unrep, shi, &sci);
 
 			if (cn_unrep->error_bound > FLT_EPSILON) {
 				single_light_contrib(unrep->lar, shi, &i, &i_noshad, &t);

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-29 11:37:11 UTC (rev 15863)
+++ branches/soc-2008-unclezeiv/source/blender/render/intern/source/shadeoutput.c	2008-07-29 11:53:43 UTC (rev 15864)
@@ -2014,6 +2014,9 @@
 			}
 		}
 #endif
+
+		/* specularity */
+		shadfac[3]*= phongcorr;	/* note, shadfac not allowed to be stored nonlocal */
 		

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list