[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [16780] branches/soc-2008-unclezeiv/source /blender/render/intern/source/lightcuts.c: Initial commit of " multiple representatives" feature.

Davide Vercelli davide.vercelli at gmail.com
Sun Sep 28 11:17:43 CEST 2008


Revision: 16780
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=16780
Author:   unclezeiv
Date:     2008-09-28 11:17:38 +0200 (Sun, 28 Sep 2008)

Log Message:
-----------
Initial commit of "multiple representatives" feature. Long story short: this is a new option that should convert banding into noise.

Issues:
- slows down rendering significantly but there's still plenty of room for optimizations
- the refactoring required by this feature could have broken other stuff: testers, please re-run previous tests

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-09-28 08:00:22 UTC (rev 16779)
+++ branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c	2008-09-28 09:17:38 UTC (rev 16780)
@@ -389,6 +389,80 @@
 	
 	dest->sphere= one->sphere && two->sphere;
 	dest->sphere_dist= MAX2(one->sphere_dist, two->sphere_dist);
+	
+	if (lcd->options & LC_OPT_MULT_REPR) {
+		short found, used[LC_MAX_MULT_REPR * 2];
+		float x, lum;
+		float tot_lum= 0.0f;
+		int i, j;
+		
+		memset(used, 0, sizeof(used));
+		
+		/* calc tot_lum: TODO: slow but will change! */
+		for (j= 0; j< one->mrep_len; j++)
+			tot_lum+= one->mrep_list[j].intensity;
+		for (j= 0; j< two->mrep_len; j++)
+			tot_lum+= two->mrep_list[j].intensity;
+		
+		dest->mrep_len= MAX2(one->mrep_len, two->mrep_len);
+		
+		if (dest->mrep_len < LC_MAX_MULT_REPR) {
+			if (one->mrep_len == two->mrep_len)
+				dest->mrep_len++;
+			else
+			{
+				float minlen= (float)MIN2(one->mrep_len, two->mrep_len);
+				if (BLI_frand() < minlen / dest->mrep_len)
+					dest->mrep_len++;
+			}
+		}
+		
+		dest->mrep_list= MEM_callocN(sizeof(ClusRep) * dest->mrep_len, "lc mreplist");
+		
+		for (i= 0; i< dest->mrep_len; i++) {
+			x= BLI_frand() * tot_lum;
+			found= 0;
+			
+			for (j= 0; j< one->mrep_len; j++) {
+				if (used[j])
+					continue;
+				lum= one->mrep_list[j].intensity;
+				if (x <= lum) {
+					dest->mrep_list[i].lar= one->mrep_list[j].lar;
+					dest->mrep_list[i].intensity= lum;
+					found= 1;
+					tot_lum-= lum;
+					used[j]= 1;
+					break;
+				}
+				x -= lum;
+			}
+			
+			if (found)
+				continue;
+			
+			for (j= 0; j< two->mrep_len; j++) {
+				if (used[one->mrep_len + j])
+					continue;
+				lum= two->mrep_list[j].intensity;
+				if (x <= lum) {
+					dest->mrep_list[i].lar= two->mrep_list[j].lar;
+					dest->mrep_list[i].intensity= lum;
+					found= 1;
+					tot_lum-= lum;
+					used[one->mrep_len + j]= 1;
+					break;
+				}
+				x -= lum;
+			}
+			
+			if (!found)
+				printf("TERRIBLE bug!\n");
+		}
+		
+		/* sort list and allocate list */
+		qsort(dest->mrep_list, dest->mrep_len, sizeof(ClusRep), cmp_clusrep);
+	}
 
 	(*root)++;
 	
@@ -565,6 +639,13 @@
 			clus->sphere = 1;
 			clus->sphere_dist = lar->dist;
 		}
+		
+		if (lcd->options & LC_OPT_MULT_REPR) {
+			clus->mrep_len= 1;
+			clus->mrep_list= MEM_callocN(sizeof(ClusRep), "clusrep");
+			clus->mrep_list[0].lar= clus->lar;
+			clus->mrep_list[0].intensity= INPR(colw, clus->col);
+		}
 
 		clus++;
 		tree->free++;
@@ -2104,21 +2185,43 @@
 	dbg_convert[tree->node]= 0;
 #endif
 	if (node->error_bound > FLT_EPSILON) {
-		single_light_contrib(clus->lar, si->shi, &i, &i_noshad, &t);
+		LampRen *lar= clus->lar;
+		float intensity= clus->intensity;
+		if (lcd->options & LC_OPT_MULT_REPR && clus->mrep_len > 1) {
+			int i;
+			float rand, tot_lum= 0.0f; 
+			/* XXX */
+			for (i= 0; i< clus->mrep_len; i++)
+				tot_lum+= clus->mrep_list[i].intensity;
+			
+			rand= BLI_frand() * tot_lum;
+			
+			for (i= 0; i< clus->mrep_len; i++) {
+				float lum= clus->mrep_list[i].intensity;
+				if (rand < lum) {
+					lar= clus->mrep_list[i].lar;
+					intensity= clus->luminance / lum;
+					break;
+				}
+				rand -= lum;
+			}
+		}
+		single_light_contrib(lar, si->shi, &i, &i_noshad, &t);
 		lcd->stat_rays_shot++;
 		node->contr_factor= MAX2(i, 0.0f);
 		node->contr_factor_spec= MAX2(t, 0.0f);
-		node->f_clus= node->contr_factor * clus->intensity;
-		node->f_clus_spec= node->contr_factor_spec * clus->intensity;
+		node->f_clus= node->contr_factor * intensity;
+		node->f_clus_spec= node->contr_factor_spec * intensity;
 		VECADDFAC(si->totest_shad, si->totest_shad, clus->col, node->f_clus);
 		VECADDFAC(si->totest_spec, si->totest_spec, clus->col, node->f_clus_spec);
 
 		/* XXX this part only for root ? */
 		if(si->shi->passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW)) {
 			node->contr_factor_noshad= MAX2(i_noshad, 0.0f);
-			node->f_clus_noshad= node->contr_factor_noshad * clus->intensity;
+			node->f_clus_noshad= node->contr_factor_noshad * intensity;
 			VECADDFAC(si->totest_noshad, si->totest_noshad, clus->col, node->f_clus_noshad);
 		}
+		
 #ifdef LIGHTCUTS_DEBUG
 		dbg_totlum+= node->contr_factor * clus->luminance;
 #endif
@@ -2129,7 +2232,7 @@
 			si->used++;
 			
 			/* XXX unneeded for root ? */
-			if (clus->lar->lightcuts_options & LC_LAR_INDIRECT) {
+			if (lar->lightcuts_options & LC_LAR_INDIRECT) {
 				si->vpl_queue[si->vpl_to_cap]= node - si->cut_nodes;
 				si->vpl_to_cap++;
 			}
@@ -2152,7 +2255,6 @@
 	SampleInfo si;
 	
 	int it= 0;
-	float i, i_noshad, t;
 	float noropp[3];
 	float mirdir[3];
 	
@@ -2305,108 +2407,66 @@
 			 */
 			VECADDFAC(si.totest_shad, si.totest_shad, hinode->col, -cn_hinode->f_clus);
 			VECADDFAC(si.totest_spec, si.totest_spec, hinode->col, -cn_hinode->f_clus_spec);
+			
+			if(si.shi->passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW))
+				VECADDFAC(si.totest_noshad, si.totest_noshad, rep->col, -cn_hinode->f_clus_noshad);
+							
 #ifdef LIGHTCUTS_DEBUG
 			dbg_totlum-= cn_hinode->contr_factor * hinode->luminance;
 #endif
 			
-			/* 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, si.shi->co) * calc_material_eb(rep, si.shi, &si.sci);
+			/* TODO: check if we can save some calculations with MR */
+			if (lcd->options & LC_OPT_MULT_REPR)
+				fill_cut_node(lcd, cn_rep, rep, &si);
+			else
+			{
+				/* 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, si.shi->co) * calc_material_eb(rep, si.shi, &si.sci);
 
-			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;
-				cn_rep->f_clus_spec= cn_hinode->contr_factor_spec * rep->intensity;
-				VECADDFAC(si.totest_shad, si.totest_shad, rep->col, cn_rep->f_clus);
-				VECADDFAC(si.totest_spec, si.totest_spec, rep->col, cn_rep->f_clus_spec);
+				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;
+					cn_rep->f_clus_spec= cn_hinode->contr_factor_spec * rep->intensity;
+					VECADDFAC(si.totest_shad, si.totest_shad, rep->col, cn_rep->f_clus);
+					VECADDFAC(si.totest_spec, si.totest_spec, rep->col, cn_rep->f_clus_spec);
 #ifdef LIGHTCUTS_DEBUG
-				dbg_totlum+= rep->luminance * cn_rep->contr_factor;
+					dbg_totlum+= rep->luminance * cn_rep->contr_factor;
 #endif
 
-				if (!IS_LEAF(rep))
-					BLI_heap_insert(si.cut, -cn_rep->error_bound * rep->luminance, cn_rep);
-				else {
-					si.used++;
-					
-					if (rep->lar->lightcuts_options & LC_LAR_INDIRECT) {
-						si.vpl_queue[si.vpl_to_cap]= cn_rep - si.cut_nodes;
-						si.vpl_to_cap++;
-					}
-					
-#ifdef LIGHTCUTS_DEBUG
-					if (lcd->dbg_options & LC_DBG_TRAV_A_NODE_PRINT && lcd->dbg_first_pixel==0)
-						printf("A t:%d id:%4d eb:%7.5f fc:%7.5f\n",
-								CLUSTER_TYPE_TO_ARRAY_IDX(cn_rep->type), cn_rep->id,
-								cn_rep->error_bound, cn_rep->f_clus);
-#endif
-				}
-			}
-			else
-				si.used++;
-			si.used_type[CLUSTER_TYPE_TO_ARRAY_IDX(cn_rep->type)]++;
+					if (!IS_LEAF(rep))
+						BLI_heap_insert(si.cut, -cn_rep->error_bound * rep->luminance, cn_rep);
+					else {
+						si.used++;
 
-			/* for the "unrepresented" light we have to compute stuff from scratch */
-			{
-				LightcutsCluster *clus= unrep;
-				CutNode *node = cn_unrep;
-				SampleInfo *ssi = &si;
-				//fill_cut_node(lcd, node, clus, &si);
+						if (rep->lar->lightcuts_options & LC_LAR_INDIRECT) {
+							si.vpl_queue[si.vpl_to_cap]= cn_rep - si.cut_nodes;
+							si.vpl_to_cap++;
+						}
 
-#if 1
-				node->id= clus->id;
-				node->type= clus->type;
-				node->error_bound= calc_geometric_eb(lcd, clus, ssi->shi->co) * calc_material_eb(clus, ssi->shi, &ssi->sci);
-	
-				if (node->error_bound > FLT_EPSILON) {
-					single_light_contrib(clus->lar, ssi->shi, &i, &i_noshad, &t);
-					lcd->stat_rays_shot++;
-					node->contr_factor= MAX2(i, 0.0f);
-					node->contr_factor_spec= MAX2(t, 0.0f);
-					node->f_clus= node->contr_factor * clus->intensity;
-					node->f_clus_spec= node->contr_factor_spec * clus->intensity;
-					VECADDFAC(ssi->totest_shad, ssi->totest_shad, clus->col, node->f_clus);
-					VECADDFAC(ssi->totest_spec, ssi->totest_spec, clus->col, node->f_clus_spec);
-	#ifdef LIGHTCUTS_DEBUG
-					dbg_totlum+= clus->luminance * node->contr_factor;
-	#endif
-	
-					if (!IS_LEAF(clus))
-						BLI_heap_insert(ssi->cut, -node->error_bound * clus->luminance, node);
-					else {
-						ssi->used++;
-						
-						if (clus->lar->lightcuts_options & LC_LAR_INDIRECT) {
-							ssi->vpl_queue[ssi->vpl_to_cap]= node - ssi->cut_nodes;
-							ssi->vpl_to_cap++;
-						}
-						
-	#ifdef LIGHTCUTS_DEBUG
+#ifdef LIGHTCUTS_DEBUG
 						if (lcd->dbg_options & LC_DBG_TRAV_A_NODE_PRINT && lcd->dbg_first_pixel==0)
 							printf("A t:%d id:%4d eb:%7.5f fc:%7.5f\n",
-									CLUSTER_TYPE_TO_ARRAY_IDX(node->type), node->id,
-									node->error_bound, node->f_clus);
-	#endif
+									CLUSTER_TYPE_TO_ARRAY_IDX(cn_rep->type), cn_rep->id,
+									cn_rep->error_bound, cn_rep->f_clus);
+#endif
 					}
 				}
 				else
-					ssi->used++;
-				ssi->used_type[CLUSTER_TYPE_TO_ARRAY_IDX(node->type)]++;
-#endif
+					si.used++;
+				si.used_type[CLUSTER_TYPE_TO_ARRAY_IDX(cn_rep->type)]++;
+				
+				if(si.shi->passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW)) {
+					cn_rep->contr_factor_noshad= cn_hinode->contr_factor_noshad;
+					cn_rep->f_clus_noshad= cn_hinode->contr_factor_noshad * rep->intensity;
+					VECADDFAC(si.totest_noshad, si.totest_noshad, rep->col, cn_rep->f_clus_noshad);
+				}
 			}
 
-			if(si.shi->passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW)) {
-				VECADDFAC(si.totest_noshad, si.totest_noshad, rep->col, -cn_hinode->f_clus_noshad);
-
-				cn_rep->contr_factor_noshad= cn_hinode->contr_factor_noshad;
-				cn_rep->f_clus_noshad= cn_hinode->contr_factor_noshad * rep->intensity;
-				VECADDFAC(si.totest_noshad, si.totest_noshad, rep->col, cn_rep->f_clus_noshad);
-

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list