[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [15423] branches/soc-2008-unclezeiv/source /blender/render/intern: Phong specularity is now supported, but more extensive testing is required.

Davide Vercelli davide.vercelli at gmail.com
Fri Jul 4 04:04:17 CEST 2008


Revision: 15423
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=15423
Author:   unclezeiv
Date:     2008-07-04 04:03:03 +0200 (Fri, 04 Jul 2008)

Log Message:
-----------
Phong specularity is now supported, but more extensive testing is required.
Also: light contribution function is now called directly, the callback mechanism was not actually needed.

Modified Paths:
--------------
    branches/soc-2008-unclezeiv/source/blender/render/intern/include/lightcuts.h
    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/include/lightcuts.h
===================================================================
--- branches/soc-2008-unclezeiv/source/blender/render/intern/include/lightcuts.h	2008-07-04 01:03:50 UTC (rev 15422)
+++ branches/soc-2008-unclezeiv/source/blender/render/intern/include/lightcuts.h	2008-07-04 02:03:03 UTC (rev 15423)
@@ -37,8 +37,6 @@
 
 void lightcuts_free(struct LightcutsData **p);
 
-typedef void (*LightContribFunc)(LampRen *lar, ShadeInput *shi, float *i, float *i_noshad);
+void lightcuts_do_lights(struct LightcutsData *lcd, ShadeInput *shi, ShadeResult *shr);
 
-void lightcuts_do_lights(struct LightcutsData *lcd, LightContribFunc get_contrib, ShadeInput *shi, ShadeResult *shr);
-
 #endif /*LIGHTCUTS_H_*/

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-04 01:03:50 UTC (rev 15422)
+++ branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c	2008-07-04 02:03:03 UTC (rev 15423)
@@ -36,6 +36,7 @@
 #include "BLI_rand.h"
 #include "DNA_group_types.h"
 #include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
 #include "DNA_listBase.h"
 #include "MEM_guardedalloc.h"
 #include "PIL_time.h"
@@ -104,8 +105,10 @@
 	float error_bound;
 	float contr_factor;
 	float contr_factor_noshad;
+	float contr_factor_spec;
 	float f_clus;
 	float f_clus_noshad;
+	float f_clus_spec;
 } CutNode;
 
 typedef struct LightcutsTree {
@@ -150,6 +153,7 @@
 #define VECNEG(v) {*(v)=-*(v); *(v+1)=-*(v+1); *(v+2)=-*(v+2);}
 /* TODO: tentative calculation, will look better into it */
 #define LC_LUMINOSITY(c) (0.299*(c)[0] + 0.587*(c)[1] + 0.114*(c)[2])
+#define LC_LUMINOSITY2(c1,c2) (LC_LUMINOSITY(c1)+LC_LUMINOSITY(c2))
 /* #define LC_LUMINOSITY(c) (0.316*c[0] + 0.460*c[1] + 0.224*c[2]) */
 #define IS_LEAF(node) (!(node)->child1 && !(node)->child2)
 
@@ -895,29 +899,42 @@
 	return max[2] / sqrt(xsq + ysq + max[2]*max[2]);
 }
 
-/* fill in tangent space matrix tsm given normal */
-static void get_tangent_space_matrix(float tsm[3][3], float *nor)
+/* fill in a new matrix describing a space where axis is z+ */
+static void get_axis_matrix(float amat[3][3], float *axis)
 {
-	float normat[3][3];
+	float mat[3][3];
 	
-	VECCOPY(normat[2], nor);
-	VecOrthoBasisf(normat[2], normat[0], normat[1]);
+	VECCOPY(mat[2], axis);
+	VecOrthoBasisf(mat[2], mat[0], mat[1]);
 
-	/* now we have a proper tangent-to-world matrix: let's invert it */
-	Mat3Inv(tsm, normat);
+	/* now we have a proper local-to-world matrix: let's invert it */
+	Mat3Inv(amat, mat);
 }
 
+float spec(float inp, int hard);
+
 /* error bound: material term */
-/* TODO: currently supporting only diffuse */
-static float calc_material_eb(float tsm[3][3], LightcutsCluster *clus, float *pos)
+/* TODO: currently supporting only lambertian diffuse and Phong specular */
+static float calc_material_eb(LightcutsCluster *clus, ShadeInput *shi, float tsm[3][3], float *tspos, float msm[3][3], float *mspos)
 {
-	float tmin[3], tmax[3];
+	float tmin[3], tmax[3], eb_diff, eb_spec=0.0f;
 	transform_aabb(tsm, clus->min, clus->max, tmin, tmax);
 	if (clus->type != CLUSTER_SUN) {
-		VECADD(tmin, pos, tmin);
-		VECADD(tmax, pos, tmax);
+		VECADD(tmin, tspos, tmin);
+		VECADD(tmax, tspos, tmax);
 	}
-	return MAX2(compute_cosine_bound(tmin, tmax), 0.0);
+	eb_diff= MAX2(compute_cosine_bound(tmin, tmax), 0.0) * shi->refl;
+	/* TODO: optimize */
+	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;
+		eb_spec= spec(MAX2(compute_cosine_bound(tmin, tmax), 0.0), shi->har) * shi->spec;
+	}
+	return eb_diff + eb_spec;
 }
 
 /* error bound: geometric term */
@@ -951,7 +968,7 @@
 		float cos_t, angle;
 		float tsm[3][3];
 		
-		get_tangent_space_matrix(tsm, clus->cone_dir);
+		get_axis_matrix(tsm, clus->cone_dir);
 		
 		VECSUB(newmax, pos, clus->min);
 		VECSUB(newmin, pos, clus->max);
@@ -975,21 +992,21 @@
 	}
 }
 
-/*
- * what about intensity? which one should we use?
- * RESOLUTION: the one of the lamp, then adjusted
- */
+void single_light_contrib(LampRen *lar, ShadeInput *shi, float *pi, float *pi_noshad, float *pt);
 
-void lightcuts_do_lights(LightcutsData *lcd, LightContribFunc get_contrib, ShadeInput *shi, ShadeResult *shr)
+void lightcuts_do_lights(LightcutsData *lcd, ShadeInput *shi, ShadeResult *shr)
 {
-	/* TODO: show that this size is always sufficient */
 	CutNode *cut_nodes;
 	int free_node= 1;
 	int it= 0;
 	int used= 0;
-	float i, i_noshad;
+	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];
+	float noropp[3];
+	float mirdir[3];
 	LightcutsCluster *array;
 
 	/* 
@@ -1000,8 +1017,9 @@
 	Heap *cut= BLI_heap_new();
 
 	/* this is the total radiance estimate, continuously updated */
-	float totest[3]= {0.0f, 0.0f, 0.0f};
+	float totest_shad[3]= {0.0f, 0.0f, 0.0f};
 	float totest_noshad[3]= {0.0f, 0.0f, 0.0f};
+	float totest_spec[3]= {0.0f, 0.0f, 0.0f};
 
 #ifdef LIGHTCUTS_DEBUG
 	int dbg_convert[lcd->max_lights * 2]; /* from cluster id to index in cut_nodes */
@@ -1010,14 +1028,29 @@
 #endif
 	
 	/* XXX: shi->vn seems to point inside the mesh, investigate; works inverted like this */
-	VECCOPY(tspos, shi->vn);
-	VECNEG(tspos);
-	get_tangent_space_matrix(tsm, tspos);
+	VECCOPY(noropp, shi->vn);
+	VECNEG(noropp);
+	get_axis_matrix(tsm, noropp);
 	
 	/* get sample coordinates in tangent space */
 	VECCOPY(tspos, shi->co);
 	Mat3MulVecfl(tsm, tspos);
 	VECNEG(tspos);
+	
+	/* create mirror direction space */
+	{
+		float nor2[3];
+		VECCOPY(nor2, noropp);
+		VECCOPY(mirdir, shi->co);
+		Normalize(mirdir);
+		VecMulf(nor2, -2 * Inpf(mirdir, nor2));
+		VecAddf(mirdir, nor2, mirdir);
+		
+		get_axis_matrix(msm, mirdir);
+		VECCOPY(mspos, shi->co);
+		Mat3MulVecfl(msm, mspos);
+		VECNEG(mspos);
+	}
 
 	cut_nodes= lcd->cut_nodes + shi->thread * lcd->cut_nodes_size;
 
@@ -1035,16 +1068,19 @@
 
 				root->id= tree->root;
 				root->type= clus->type;
-				root->error_bound= calc_geometric_eb(lcd, clus, shi->co) * calc_material_eb(tsm, clus, tspos) * shi->refl;
+				root->error_bound= calc_geometric_eb(lcd, clus, shi->co) * calc_material_eb(clus, shi, tsm, tspos, msm, mspos);
 #ifdef LIGHTCUTS_DEBUG
 				dbg_convert[tree->root]= 0;
 #endif
 				if (root->error_bound > FLT_EPSILON) {
-					get_contrib(clus->lar, shi, &i, &i_noshad);
+					single_light_contrib(clus->lar, shi, &i, &i_noshad, &t);
 					lcd->stat_rays_shot++;
 					root->contr_factor= MAX2(i, 0.0f);
+					root->contr_factor_spec= MAX2(t, 0.0f);
 					root->f_clus= root->contr_factor * clus->intensity;
-					VECADDFAC(totest, totest, clus->col, root->f_clus);
+					root->f_clus_spec= root->contr_factor_spec * clus->intensity;
+					VECADDFAC(totest_shad, totest_shad, clus->col, root->f_clus);
+					VECADDFAC(totest_spec, totest_spec, clus->col, root->f_clus_spec);
 
 					if(shi->passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW)) {
 						root->contr_factor_noshad= MAX2(i_noshad, 0.0f);
@@ -1101,7 +1137,7 @@
 		}
 #endif
 
-		if (LC_LUMINOSITY(totest) * lcd->error_rate > cn_hinode->error_bound * hinode->luminance) {
+		if (LC_LUMINOSITY2(totest_shad, totest_spec) * lcd->error_rate > cn_hinode->error_bound * hinode->luminance) {
 			break;
 		} else {
 			LightcutsCluster *rep= &array[hinode->child1];
@@ -1124,7 +1160,8 @@
 			 * but please note that it's the same quantity
 			 * we are not calculating it in different ways
 			 */
-			VECADDFAC(totest, totest, hinode->col, -cn_hinode->f_clus);
+			VECADDFAC(totest_shad, totest_shad, hinode->col, -cn_hinode->f_clus);
+			VECADDFAC(totest_spec, totest_spec, hinode->col, -cn_hinode->f_clus_spec);
 #ifdef LIGHTCUTS_DEBUG
 			dbg_totlum-= cn_hinode->contr_factor * hinode->luminance;
 #endif
@@ -1132,12 +1169,15 @@
 			/* 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(tsm, rep, tspos) * shi->refl;
+			cn_rep->error_bound= calc_geometric_eb(lcd, rep, shi->co) * calc_material_eb(rep, shi, tsm, tspos, msm, mspos);
 
 			if (cn_rep->error_bound > FLT_EPSILON) {
 				cn_rep->contr_factor= cn_hinode->contr_factor;
+				cn_rep->contr_factor_spec= cn_hinode->contr_factor_spec;
 				cn_rep->f_clus= cn_hinode->contr_factor * rep->intensity;
-				VECADDFAC(totest, totest, rep->col, cn_rep->f_clus);
+				cn_rep->f_clus_spec= cn_hinode->contr_factor_spec * rep->intensity;
+				VECADDFAC(totest_shad, totest_shad, rep->col, cn_rep->f_clus);
+				VECADDFAC(totest_spec, totest_spec, rep->col, cn_rep->f_clus_spec);
 #ifdef LIGHTCUTS_DEBUG
 				dbg_totlum+= rep->luminance * cn_rep->contr_factor;
 #endif
@@ -1153,14 +1193,17 @@
 			/* 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(tsm, unrep, tspos) * shi->refl;
+			cn_unrep->error_bound= calc_geometric_eb(lcd, unrep, shi->co) * calc_material_eb(unrep, shi, tsm, tspos, msm, mspos);
 
 			if (cn_unrep->error_bound > FLT_EPSILON) {
-				get_contrib(unrep->lar, shi, &i, &i_noshad);
+				single_light_contrib(unrep->lar, shi, &i, &i_noshad, &t);
 				lcd->stat_rays_shot++;
 				cn_unrep->contr_factor= MAX2(i, 0.0f);
+				cn_unrep->contr_factor_spec= MAX2(t, 0.0f);
 				cn_unrep->f_clus= cn_unrep->contr_factor * unrep->intensity;
-				VECADDFAC(totest, totest, unrep->col, cn_unrep->f_clus);
+				cn_unrep->f_clus_spec= cn_unrep->contr_factor_spec * unrep->intensity;
+				VECADDFAC(totest_shad, totest_shad, unrep->col, cn_unrep->f_clus);
+				VECADDFAC(totest_spec, totest_spec, unrep->col, cn_unrep->f_clus_spec);
 #ifdef LIGHTCUTS_DEBUG
 				dbg_totlum+= unrep->luminance * cn_unrep->contr_factor;
 #endif
@@ -1192,9 +1235,13 @@
 	 * an updated TOTEST value (even thought numerically questionable?)
 	 */
 
-	shr->shad[0]+= totest[0]*shi->r;
-	shr->shad[1]+= totest[1]*shi->g;
-	shr->shad[2]+= totest[2]*shi->b;
+	shr->shad[0]+= totest_shad[0]*shi->r;
+	shr->shad[1]+= totest_shad[1]*shi->g;

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list