[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [16066] branches/soc-2008-unclezeiv/source /blender: - preliminary stuff to support "instant radiosity" -like indirect illumination.

Davide Vercelli davide.vercelli at gmail.com
Tue Aug 12 17:06:49 CEST 2008


Revision: 16066
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=16066
Author:   unclezeiv
Date:     2008-08-12 17:06:49 +0200 (Tue, 12 Aug 2008)

Log Message:
-----------
- preliminary stuff to support "instant radiosity"-like indirect illumination. This is a work in progress: in particular, it currently works only for area lights and it does not take the surface color into account (=no color bleeding yet)
- raytrace.c: don't test for self intersection if the ray was not originated from a face (maybe there's another way to do this, the API is a bit obscure)
- shadeoutput.c: minor readability change

Modified Paths:
--------------
    branches/soc-2008-unclezeiv/source/blender/makesdna/DNA_scene_types.h
    branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c
    branches/soc-2008-unclezeiv/source/blender/render/intern/source/raytrace.c
    branches/soc-2008-unclezeiv/source/blender/render/intern/source/shadeoutput.c
    branches/soc-2008-unclezeiv/source/blender/src/buttons_scene.c

Modified: branches/soc-2008-unclezeiv/source/blender/makesdna/DNA_scene_types.h
===================================================================
--- branches/soc-2008-unclezeiv/source/blender/makesdna/DNA_scene_types.h	2008-08-12 13:30:17 UTC (rev 16065)
+++ branches/soc-2008-unclezeiv/source/blender/makesdna/DNA_scene_types.h	2008-08-12 15:06:49 UTC (rev 16066)
@@ -318,7 +318,9 @@
 	int lightcuts_max_cut;
 	int lightcuts_area_density;
 	int lightcuts_env_map;
-	int pad4;
+	float lightcuts_indir_fac;
+	int lightcuts_indirect;
+	int lightcuts_random_dirs;
 } RenderData;
 
 /* control render convert and shading engine */

Modified: branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c
===================================================================
--- branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c	2008-08-12 13:30:17 UTC (rev 16065)
+++ branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c	2008-08-12 15:06:49 UTC (rev 16066)
@@ -49,6 +49,7 @@
 #include "blendef.h"
 #include "pixelshading.h"
 #include "render_types.h"
+#include "shading.h"
 
 /* #define LIGHTCUTS_DEBUG */
 
@@ -149,6 +150,7 @@
 	LightcutsTree trees[_TREES_SIZE];
 
 	int light_counter;
+	int vpl_counter;
 
 	float error_rate;
 	int max_lights;
@@ -159,7 +161,10 @@
 	int stat_samples;
 	int stat_cut_size;
 	int stat_rays_shot;
-	float bb_diag_sq;
+	float scene_diag;
+	float indir_fac;
+	int do_indir;
+	int random_dirs;
 	
 	double start_time;
 	double tree_creation_time;
@@ -299,6 +304,7 @@
 	return rep;
 }
 
+#if 0
 static void find_and_insert_new_min(Heap * heap, LightcutsCluster * array, int size, LightcutsClusterPair * pair, int id, int from, float c)
 {
 	LightcutsCluster * el = &array[id];
@@ -336,6 +342,7 @@
 		BLI_heap_insert(heap, metric, pair);
 	}
 }
+#endif
 
 static void cb_update_metric_max_dist(void *data, int index, float *val, float *dist)
 {
@@ -505,6 +512,7 @@
 }
 #endif
 
+#if 0
 static void lightcuts_build_tree(LightcutsTree *tree, float c)
 {
 	int i, cluster_id = 0;
@@ -563,6 +571,7 @@
 
 	MEM_freeN(pair_array);
 }
+#endif
 
 /* this one uses kdtree */
 static void lightcuts_build_tree2(LightcutsTree *tree, float c)
@@ -1004,6 +1013,94 @@
 	}
 }
 
+static void get_cosine_weighted_random_direction(float *dir)
+{
+	float theta, phi, rvar;
+	float sin_th;
+	
+	/* cosine weighted angle to axis Z */
+	do {
+		rvar= BLI_frand();
+		theta= BLI_frand() * 0.5 * M_PI;
+		sin_th= sinf(theta);
+	} while (rvar < sin_th);
+	
+	dir[2]= sqrtf(1 - sin_th * sin_th);
+	
+	/* uniformly weighted angle around axis Z */
+	phi= BLI_frand() * M_PI;
+	dir[0]= cosf(phi) * sin_th;
+	dir[1]= sinf(phi) * sin_th;
+}
+
+static void add_virtual_point_light(Render * re, LightcutsData *lcd, LampRen *orig, float *col)
+{
+	GroupObject *gonew;
+	LampRen *lar;
+	VlakRen *vla;
+	Isect isec;
+	float tmp[3], dist;
+	
+	isec.mode= RE_RAY_MIRROR; /* TODO: check */
+	isec.faceorig= NULL;
+	isec.oborig= 0;
+	VECCOPY(isec.start, orig->co);
+	if (lcd->random_dirs) {
+		get_cosine_weighted_random_direction(isec.vec);
+		Mat3MulVecfl(orig->mat, isec.vec);
+		VECNEG(isec.vec);
+	}
+	else
+		VECCOPY(isec.vec, orig->vec);
+	VECADDFAC(isec.end, isec.start, isec.vec, lcd->scene_diag);
+	
+	if (!RE_ray_tree_intersect(re->raytree, &isec))
+		return;
+	
+	vla= (VlakRen*)isec.face;
+	
+	lar= (LampRen *)MEM_callocN(sizeof(LampRen), "lampren");
+	init_lamp(re, lar);
+	/* XXX: fixed distance or proportional to orig->dist? */
+	lar->dist= orig->dist / 2;
+	lar->distkw= lar->dist * lar->dist;
+	lar->lay= orig->lay;
+	VECCOPY(lar->vec, vla->n);
+	VECNEG(lar->vec);
+	VECCOPY(lar->mat[2], vla->n);
+	VecOrthoBasisf(lar->mat[2], lar->mat[0], lar->mat[1]);
+	Mat3Inv(lar->imat, lar->mat);
+	lar->type = LA_SPOT;
+
+	/* XXX: err... something better than 0.01? */
+	VECADDFAC(lar->co, isec.start, isec.vec, isec.labda - 0.01);
+
+	/* TODO: read color */
+	lar->energy= lamp_get_visibility(orig, lar->co, tmp, &dist);
+	lar->energy*= 1.0 / (lcd->indir_fac * lcd->do_indir);
+	lar->r= lar->energy * col[0];// * isec.col[0];
+	lar->g= lar->energy * col[1];// * isec.col[1];
+	lar->b= lar->energy * col[2];// * isec.col[2];
+
+#ifdef LIGHTCUTS_DEBUG
+	//printf("coordinates: %4f %4f %4f\n", lar->co[0], lar->co[1], lar->co[2]);
+#endif
+
+	gonew= MEM_callocN(sizeof(GroupObject), "groupobject");
+	BLI_addtail(&lcd->pointlights, gonew);
+	/* XXX: see remarks on similar code in convert_environment_map */
+	gonew->ob= 0;
+	
+	BLI_addtail(&re->lampren, lar);
+	/* check deallocation */
+	gonew->lampren= lar;
+
+	lcd->trees[TREE_SPOT].counter++;
+	lcd->light_counter++;
+	lcd->vpl_counter++;
+	lar->ray_samp_method = LA_SAMP_CONSTANT;
+}
+
 static void convert_area_light(Render * re, LightcutsData *lcd, LampRen *orig)
 {
 	GroupObject *gonew;
@@ -1012,7 +1109,7 @@
 	float xdir[3], ydir[3], col[3];
 	float stepx, stepy, texvec[2];
 	float p, u, v;
-	int k, kk, pos, n;
+	int k, kk, pos, n, i;
 	int use_texture= 0;
 	int tex_nr;
 	
@@ -1028,7 +1125,7 @@
 	factor= 2.0 * M_PI * orig->dist / (4.0 * realw * realh * n);
 
 	/* XXX: TODO: temporary check just to avoid freezing on undue densities */
-	if (lcd->light_counter + n > re->r.lightcuts_max_lights) {
+	if (lcd->light_counter + n * (1 + lcd->do_indir) > re->r.lightcuts_max_lights) {
 		printf("Err: required light density would violate light limit\n");
 		return;
 	}
@@ -1107,6 +1204,10 @@
 		lcd->trees[TREE_SPOT].counter++;
 		lcd->light_counter++;
 		lar->ray_samp_method = LA_SAMP_CONSTANT;
+		
+		/* indirect lighting */
+		for (i= 0; i < lcd->do_indir; i++)
+			add_virtual_point_light(re, lcd, lar, col);
 	}
 }
 
@@ -1126,6 +1227,11 @@
 	re->lcdata = lcd = MEM_callocN(sizeof(LightcutsData), "LightcutsData");
 	pointlights= &lcd->pointlights;
 	lcd->light_counter= 0;
+	lcd->indir_fac= re->r.lightcuts_indir_fac;
+	lcd->do_indir= re->r.lightcuts_indirect;
+	lcd->random_dirs= re->r.lightcuts_random_dirs;
+	lcd->error_rate= re->r.lightcuts_max_error;
+	lcd->scene_diag= RE_ray_tree_max_size(re->raytree);
 	
 	if (re->r.lightcuts_env_map > 0)
 		convert_environment_map(re, lcd, re->r.lightcuts_env_map);
@@ -1173,15 +1279,9 @@
 
 	/* XXX: this 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= MIN2(re->r.lightcuts_max_cut, lcd->light_counter);
 	lcd->start_time= PIL_check_seconds_timer();
 	
-	/* we need the scene's diagonal squared */
-	lcd->bb_diag_sq= RE_ray_tree_max_size(re->raytree);
-	printf("Scene diagonal %f\n", lcd->bb_diag_sq);
-	lcd->bb_diag_sq*= lcd->bb_diag_sq;
-	
 	re->i.infostr= "Building light trees";
 	re->stats_draw(&re->i);
 
@@ -1190,7 +1290,7 @@
 		if (lcd->trees[i].counter > 0) {
 			lightcuts_fill_array(pointlights, &lcd->trees[i], i);
 			printf("Lightcuts: building %s tree - ", tree_names[i]);
-			lightcuts_build_tree2(&lcd->trees[i], lcd->bb_diag_sq);
+			lightcuts_build_tree2(&lcd->trees[i], lcd->scene_diag * lcd->scene_diag);
 		}
 	}
 	
@@ -1824,7 +1924,7 @@
 	printf("Lightcuts stats\n"
 	       "---------------\n"
 	       "Computed samples: %d\n"
-	       "Number of (point) lights: %d (%dl + %ds + %do)\n"
+	       "Number of (point) lights: %d (%dl + %ds + %do) (%dd + %di)\n"
 	       "Requested error rate: %.3f\n"
 	       "Max cut: %d\n"
 	       "Average cut size: %.2f\n"
@@ -1832,6 +1932,7 @@
 	       "---------------\n",
 		lcd->stat_samples, lcd->light_counter,
 		lcd->trees[TREE_LOCAL].counter, lcd->trees[TREE_SUN].counter, lcd->trees[TREE_SPOT].counter,
+		lcd->light_counter - lcd->vpl_counter, lcd->vpl_counter,
 		lcd->error_rate,
 		lcd->max_cut,
 		(float)lcd->stat_cut_size / (float)lcd->stat_samples,

Modified: branches/soc-2008-unclezeiv/source/blender/render/intern/source/raytrace.c
===================================================================
--- branches/soc-2008-unclezeiv/source/blender/render/intern/source/raytrace.c	2008-08-12 13:30:17 UTC (rev 16065)
+++ branches/soc-2008-unclezeiv/source/blender/render/intern/source/raytrace.c	2008-08-12 15:06:49 UTC (rev 16066)
@@ -931,7 +931,7 @@
 		intersection to be detected in its neighbour face */
 		
 		if(is->facecontr && is->faceisect);	// optimizing, the tests below are not needed
-		else if(is->labda< .1) {
+		else if(is->labda< .1 && is->faceorig) {
 			RayFace *face= is->faceorig;
 			float *origv1, *origv2, *origv3, *origv4;
 			short de= 0;

Modified: branches/soc-2008-unclezeiv/source/blender/render/intern/source/shadeoutput.c
===================================================================
--- branches/soc-2008-unclezeiv/source/blender/render/intern/source/shadeoutput.c	2008-08-12 13:30:17 UTC (rev 16065)
+++ branches/soc-2008-unclezeiv/source/blender/render/intern/source/shadeoutput.c	2008-08-12 15:06:49 UTC (rev 16066)
@@ -1072,7 +1072,7 @@
 		float visifac= 1.0f, t;
 		
 		VECSUB(lv, co, lar->co);
-		*dist= sqrt( INPR(lv, lv));
+		*dist= sqrt(INPR(lv, lv));
 		t= 1.0f/dist[0];
 		VECMUL(lv, t);
 		
@@ -1115,42 +1115,39 @@
 					visifac*= t/lar->dist;
 			}
 			
-			if(visifac > 0.0f) {
-				if(lar->type==LA_SPOT) {
-					float inpr;
-					
-					if(lar->mode & LA_SQUARE) {
-						if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0f) {
-							float lvrot[3], x;
-							
-							/* rotate view to lampspace */
-							VECCOPY(lvrot, lv);
-							MTC_Mat3MulVecfl(lar->imat, lvrot);
-							
-							x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2]));
-							/* 1.0f/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
-							
-							inpr= 1.0f/(sqrt(1.0f+x*x));
-						}
-						else inpr= 0.0f;
+			if(lar->type==LA_SPOT && visifac > 0.0f) {
+				float inpr;
+				
+				inpr= INPR(lv, lar->vec);
+				
+				if(lar->mode & LA_SQUARE) {
+					if(inpr>0.0f) {
+						float lvrot[3], x;
+						
+						/* rotate view to lampspace */
+						VECCOPY(lvrot, lv);
+						MTC_Mat3MulVecfl(lar->imat, lvrot);
+						
+						x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2]));
+						/* 1.0f/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
+						
+						inpr= 1.0f/(sqrt(1.0f+x*x));
 					}
-					else {
-						inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
+					else inpr= 0.0f;
+				}
+				
+				t= lar->spotsi;
+				if(inpr<=t) 
+					visifac= 0.0f;
+				else {
+					t= inpr-t;
+					if(t<lar->spotbl && lar->spotbl!=0.0f) {
+						/* soft area */
+						float i= t/lar->spotbl;
+						t= i*i;
+						inpr*= (3.0f*t-2.0f*t*i);
 					}
-					
-					t= lar->spotsi;
-					if(inpr<=t) 
-						visifac= 0.0f;
-					else {

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list