[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [15107] branches/soc-2008-unclezeiv/source /blender/render/intern/source/lightcuts.c: Nodes candidates for the cut were not ordered correctly: now also cluster intensity and cluster luminosity are taken into account.

Davide Vercelli davide.vercelli at gmail.com
Tue Jun 3 23:05:37 CEST 2008


Revision: 15107
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=15107
Author:   unclezeiv
Date:     2008-06-03 23:05:37 +0200 (Tue, 03 Jun 2008)

Log Message:
-----------
Nodes candidates for the cut were not ordered correctly: now also cluster intensity and cluster luminosity are taken into account. This bug would previously surface in some scenes producing incorrect renderings (compared to "plain" ones). It's actually pretty surprising that most scenes rendered correctly!

Other fixes:
- cluster contribution was wrongly dividing by lar->energy, despite not being influenced by it
- on the other hand, when using lar->r,g,b I was not dividing by lar->energy as I should have (blender premultiplies lamp color by lamp energy while creating the render database)
- max cut is now never more than the actual number of lights (even though having that few lights doesn't make much sense)

Other changes:
- green channel in false colour now shows leaf nodes to cut nodes ratio

Modified Paths:
--------------
    branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.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-06-03 19:56:19 UTC (rev 15106)
+++ branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c	2008-06-03 21:05:37 UTC (rev 15107)
@@ -76,6 +76,7 @@
 	float contr_factor_noshad;
 	float f_clus;
 	float f_clus_noshad;
+	float luminosity;
 } CutNode;
 
 typedef struct LightcutsData {
@@ -98,7 +99,10 @@
 
 #define VEC_LEN_SQ(v) (v[0]*v[0] + 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_LUMINOSITY_3(r,g,b) (0.299*(r) + 0.587*(g) + 0.114*(b))
+#define LC_LUMINOSITY(c) (LC_LUMINOSITY_3((c)[0],(c)[1],(c)[2]))
+#define LC_LUMINOSITY_LAMP(lar) (LC_LUMINOSITY_3((lar)->r,(lar)->g,(lar)->b))
+/* #define LC_LUMINOSITY(c) (0.316*c[0] + 0.460*c[1] + 0.224*c[2]) */
 #define VECCOPYMUL(v1,v2,aS) {*(v1)= *(v2)*aS; *(v1+1)= *(v2+1)*aS; *(v1+2)= *(v2+2)*aS;}
 
 static float lightcuts_compute_metric(LightcutsCluster * one, LightcutsCluster * two)
@@ -428,7 +432,7 @@
 	/* XXX: whis should be equal to re->r.lightcuts_max_lights when light generation is in place */
 	lcd->max_lights= lcd->light_counter;
 	lcd->error_rate= re->r.lightcuts_max_error;
-	lcd->max_cut= re->r.lightcuts_max_cut;
+	lcd->max_cut= MIN2(re->r.lightcuts_max_cut, lcd->light_counter);
 	
 	/* TODO: look for a better error condition in case we have no lights */
 	if (pointlights->first) {
@@ -493,23 +497,25 @@
 	
 	{
 		CutNode *root= &cut_nodes[0];
-		LampRen *lar= lcd->array_local[lcd->root_local].lar;
+		LightcutsCluster *clus= &lcd->array_local[lcd->root_local];
+		LampRen *lar= clus->lar;
 		
 		root->id= lcd->root_local;
 		root->error_bound= calc_geometric_eb(lcd, lcd->root_local, shi->co);
+		root->luminosity= LC_LUMINOSITY_LAMP(lar) / lar->energy;
 		
 		get_contrib(lar, shi, &i, &i_noshad);
 		root->contr_factor= i;
-		root->f_clus= i * lcd->array_local[lcd->root_local].intensity / lar->energy;
-		ADDCONTR(totest, lar, root->f_clus);
+		root->f_clus= i * clus->intensity;
+		ADDCONTR(totest, lar, root->f_clus / lar->energy);
 		
 		if(shi->passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW)) {
 			root->contr_factor_noshad= i_noshad;
-			root->f_clus_noshad= i_noshad * lcd->array_local[lcd->root_local].intensity / lar->energy;
-			ADDCONTR(totest_noshad, lar, root->f_clus_noshad);
+			root->f_clus_noshad= i_noshad * clus->intensity;
+			ADDCONTR(totest_noshad, lar, root->f_clus_noshad / lar->energy);
 		}
 		
-		BLI_heap_insert(cut, -root->error_bound, root);
+		BLI_heap_insert(cut, -root->error_bound * clus->intensity * root->luminosity, root);
 	}
 	
 	/* at each iteration the heap grows by one, but we have a maximum size */
@@ -518,7 +524,7 @@
 		LightcutsCluster *parent;
 		
 		node= BLI_heap_popmin(cut);
-		if (node < cut_nodes || node >= cut_nodes + (lcd->max_lights * 2 + 1)) {
+		if (node < cut_nodes || node >= (cut_nodes + lcd->cut_nodes_size)) {
 			printf("tricky node! at %d, %d (it=%d)\n", shi->xs, shi->ys, it);
 			break;
 		}
@@ -530,7 +536,7 @@
 			continue;
 		}
 		
-		if (LC_LUMINOSITY(totest) * lcd->error_rate > node->error_bound * parent->intensity) {
+		if (LC_LUMINOSITY(totest) * lcd->error_rate > node->error_bound * parent->intensity * node->luminosity) {
 			break;
 		} else {
 			LightcutsCluster *rep= &lcd->array_local[parent->child1];
@@ -548,7 +554,7 @@
 			 * but please note that it's the same quantity
 			 * we are not calculating it in different ways
 			 */
-			ADDCONTR(totest, rep->lar, -node->f_clus);
+			ADDCONTR(totest, rep->lar, -node->f_clus / rep->lar->energy);
 			
 			/* this is a strong assumption on linearity of intensity contribution... is it strong indeed?
 			 * and numerically questionable again */
@@ -558,31 +564,33 @@
 			c_rep->id= rep->id;
 			c_rep->error_bound= calc_geometric_eb(lcd, rep->id, shi->co);
 			c_rep->contr_factor= node->contr_factor;
-			c_rep->f_clus= node->contr_factor * rep->intensity / rep->lar->energy;
-			ADDCONTR(totest, rep->lar, c_rep->f_clus);
+			c_rep->f_clus= node->contr_factor * rep->intensity;
+			c_rep->luminosity= node->luminosity;
+			ADDCONTR(totest, rep->lar, c_rep->f_clus / rep->lar->energy);
 						
-			BLI_heap_insert(cut, -c_rep->error_bound, c_rep);
+			BLI_heap_insert(cut, -c_rep->error_bound * rep->intensity * c_rep->luminosity, c_rep);
 			
 			/* for the "unrepresented" light we have to compute stuff from scratch */
 			c_unrep->id= unrep->id;
 			c_unrep->error_bound= calc_geometric_eb(lcd, unrep->id, shi->co);
 			get_contrib(unrep->lar, shi, &i, &i_noshad);
 			c_unrep->contr_factor= i;
-			c_unrep->f_clus= i * unrep->intensity / unrep->lar->energy;
-			ADDCONTR(totest, unrep->lar, c_unrep->f_clus);
+			c_unrep->f_clus= i * unrep->intensity;
+			c_unrep->luminosity= LC_LUMINOSITY_LAMP(unrep->lar) / unrep->lar->energy;
+			ADDCONTR(totest, unrep->lar, c_unrep->f_clus / unrep->lar->energy);
 			
-			BLI_heap_insert(cut, -c_unrep->error_bound, c_unrep);
+			BLI_heap_insert(cut, -c_unrep->error_bound * unrep->intensity * c_unrep->luminosity, c_unrep);
 			
 			if(shi->passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW)) {
-				ADDCONTR(totest_noshad, rep->lar, -node->f_clus_noshad);
+				ADDCONTR(totest_noshad, rep->lar, -node->f_clus_noshad / rep->lar->energy);
 				
 				c_rep->contr_factor_noshad= node->contr_factor_noshad;
-				c_rep->f_clus_noshad= node->contr_factor_noshad * rep->intensity / rep->lar->energy;
-				ADDCONTR(totest_noshad, rep->lar, c_rep->f_clus_noshad);
+				c_rep->f_clus_noshad= node->contr_factor_noshad * rep->intensity;
+				ADDCONTR(totest_noshad, rep->lar, c_rep->f_clus_noshad / rep->lar->energy);
 				
 				c_unrep->contr_factor_noshad= i_noshad;
-				c_unrep->f_clus_noshad= i_noshad * unrep->intensity / unrep->lar->energy;
-				ADDCONTR(totest_noshad, unrep->lar, c_unrep->f_clus_noshad);
+				c_unrep->f_clus_noshad= i_noshad * unrep->intensity;
+				ADDCONTR(totest_noshad, unrep->lar, c_unrep->f_clus_noshad / unrep->lar->energy);
 			}
 		}
 	}
@@ -605,8 +613,8 @@
 		VECCOPY(shr->diff, shr->shad);
 	
 	if (shi->passflag & SCE_PASS_LCFAUX) {
-		shr->faux[0]= (float)(used + BLI_heap_size(cut)) / (float)(MIN2(lcd->max_cut, lcd->light_counter));
-		shr->faux[1]= 0.5;
+		shr->faux[0]= (float)(used + BLI_heap_size(cut)) / lcd->max_cut;
+		shr->faux[1]= (float)used/(float)lcd->max_cut;
 		shr->faux[2]= 0.5;
 		shr->faux[3]= (float)((used + BLI_heap_size(cut)) > 0.0);
 	}





More information about the Bf-blender-cvs mailing list