[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [17186] branches/soc-2008-unclezeiv/source /blender: New feature: meshlights.

Davide Vercelli davide.vercelli at gmail.com
Thu Oct 23 00:06:03 CEST 2008


Revision: 17186
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17186
Author:   unclezeiv
Date:     2008-10-23 00:06:03 +0200 (Thu, 23 Oct 2008)

Log Message:
-----------
New feature: meshlights. Objects with materials having emit > 0.0 will actually emit light.

This is a preliminary commit and there are still some issues, but testing and user input is very welcome.

Also: cleaned up the code that creates a mesh with a vertex for each vpl, opening up the possibility to create other visualization meshes (for instance how the meshlights get sampled).

Modified Paths:
--------------
    branches/soc-2008-unclezeiv/source/blender/blenloader/intern/readfile.c
    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/src/buttons_scene.c

Modified: branches/soc-2008-unclezeiv/source/blender/blenloader/intern/readfile.c
===================================================================
--- branches/soc-2008-unclezeiv/source/blender/blenloader/intern/readfile.c	2008-10-22 20:30:02 UTC (rev 17185)
+++ branches/soc-2008-unclezeiv/source/blender/blenloader/intern/readfile.c	2008-10-22 22:06:03 UTC (rev 17186)
@@ -7838,8 +7838,8 @@
 					r->lightcuts_indir_fac= 100.0f;
 				if(r->lightcuts_env_map<=0.0f)
 					r->lightcuts_env_map= 4096.0f;
-				if(r->lightcuts_area_lights<=0.0f)
-					r->lightcuts_area_lights= 4000.0f;
+				if(r->lightcuts_area_lights<=0)
+					r->lightcuts_area_lights= 4000;
 				if(r->lightcuts_indir_dist<=0.0f)
 					r->lightcuts_indir_dist= 5.0f;
 				if(r->lightcuts_color_weight==0)
@@ -7848,6 +7848,8 @@
 					r->lightcuts_env_map_fac= 1.0f;
 				if(r->lightcuts_indir_bounces==0)
 					r->lightcuts_indir_bounces= 1;
+				if(r->lightcuts_meshlights==0)
+					r->lightcuts_meshlights= 4000;
 			}
 			
 			sce= sce->id.next;

Modified: branches/soc-2008-unclezeiv/source/blender/makesdna/DNA_scene_types.h
===================================================================
--- branches/soc-2008-unclezeiv/source/blender/makesdna/DNA_scene_types.h	2008-10-22 20:30:02 UTC (rev 17185)
+++ branches/soc-2008-unclezeiv/source/blender/makesdna/DNA_scene_types.h	2008-10-22 22:06:03 UTC (rev 17186)
@@ -324,6 +324,8 @@
 	int lightcuts_options;
 	float lightcuts_indir_dist;
 	float lightcuts_env_map_fac;
+	int lightcuts_meshlights;
+	int lcpad;
 	int lightcuts_debug_options;
 } RenderData;
 

Modified: branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c
===================================================================
--- branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c	2008-10-22 20:30:02 UTC (rev 17185)
+++ branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c	2008-10-22 22:06:03 UTC (rev 17186)
@@ -48,6 +48,7 @@
 
 #include "blendef.h"
 #include "pixelshading.h"
+#include "renderdatabase.h"
 #include "render_types.h"
 #include "shading.h"
 
@@ -206,6 +207,7 @@
 	float colw[3];
 	
 	float area_density;
+	float meshlights_density;
 
 	CutNode *cut_nodes;
 	int cut_nodes_size;
@@ -1440,7 +1442,7 @@
 	dir[2]= cosf(phi);
 }
 
-static void dbg_create_vpl_mesh(Render *re, LightcutsData *lcd)
+static void dbg_create_vis_mesh(Render *re, int counter, float *coords, char * name)
 {
 	int i, newlen;
 	Mesh *mesh;
@@ -1450,13 +1452,13 @@
 	Scene *scene;
 	Object *object, *camera;
 
-	mesh= add_mesh("indir_visualize");
+	mesh= add_mesh(name);
 	MEM_freeN(mesh->bb);
 	mesh->bb= NULL;
 	mesh->id.us = 0;
 
 	/* create custom vertex data arrays and copy existing vertices into it */
-	newlen = mesh->totvert + lcd->vpl_counter;
+	newlen = mesh->totvert + counter;
 	CustomData_copy( &mesh->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, newlen );
 	CustomData_copy_data( &mesh->vdata, &vdata, 0, 0, mesh->totvert );
 
@@ -1468,8 +1470,8 @@
 	/* scan the input list and insert the new vertices */
 
 	tmpvert = &newvert[mesh->totvert];
-	for( i = 0; i < lcd->vpl_counter; ++i, ++tmpvert )
-		memcpy( tmpvert->co, &lcd->dbg_vis_vpl[3 * i], sizeof(float) * 3 );
+	for( i = 0; i < counter; ++i, ++tmpvert )
+		memcpy( tmpvert->co, &coords[3 * i], sizeof(float) * 3 );
 	
 	CustomData_free( &mesh->vdata, mesh->totvert );
 	mesh->vdata = vdata;
@@ -1888,14 +1890,119 @@
 	}
 }
 
+void get_random_point_on_triangle(float *v1, float *v2, float *v3, float *res)
+{
+	float dir1[3], dir2[3];
+	float r1= BLI_frand(), r2= BLI_frand();
+	
+	VECSUB(dir1, v2, v1);
+	VECSUB(dir2, v3, v1);
+	
+	if (r1 + r2 > 1.0f) {
+		r1= 1.0 - r1;
+		r2= 1.0 - r2;
+	}
+	
+	res[0]= res[1]= res[2]= 0.0f;
+	
+	VECADDFAC(res, v1, dir1, r1);
+	VECADDFAC(res, res, dir2, r2);
+}
+
+void add_meshlight(Render *re, LightcutsData *lcd, ObjectRen *obr, VlakRen *vla, float *co, float weight)
+{
+	LampRen *lar;
+	Material *mat= vla->mat;
+	lar= MEM_callocN(sizeof(LampRen), "lampren");
+	lamp_init(re, lar);
+	lar->dist= lcd->indir_dist;
+	lar->distkw= lar->dist * lar->dist;
+	lar->lay= obr->lay;
+
+	/* TODO: how to decide specular */
+	// lar->mode |= LA_NO_SPEC;
+
+	/* lamp is oriented as (negated) face normal */
+	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;
+	VECADDFAC(lar->co, co, vla->n, -0.01);
+	/* VECCOPY(lcd->dbg_vis_vpl + 3 * lcd->light_counter, lar->co); */
+	lar->ray_samp_method= LA_SAMP_CONSTANT;
+	
+	lar->energy= mat->emit * weight;
+
+	lar->r= lar->energy * mat->r;
+	lar->g= lar->energy * mat->g;
+	lar->b= lar->energy * mat->b;
+
+	BLI_addtail(&lcd->pointlights, lar);
+
+	lcd->trees[TREE_SPOT].counter++;
+	lcd->light_counter++;
+}
+
+void add_lights_from_mesh(LightcutsData *lcd, Render *re)
+{
+	ObjectRen *obr;
+	float *v1, *v2, *v3, *v4, area, co[3], budget;
+	float density= lcd->meshlights_density;
+	float weight= 1.0f / density;
+	int a, n, i;
+	
+	for(obr=re->objecttable.first; obr; obr=obr->next) {
+		for(a=0; a<obr->totvlak; a++) {
+			VlakRen *vlr= RE_findOrAddVlak(obr, a);
+			
+			if (!vlr->mat || vlr->mat->emit == 0.0f)
+				continue;
+				
+			v1= vlr->v1->co;
+			v2= vlr->v2->co;
+			v3= vlr->v3->co;
+			if (vlr->v4)
+				v4= vlr->v4->co;
+			
+			area= AreaT3Dfl(v1, v2, v3);
+			budget= area * density;
+			n= (int)(budget);
+			if (BLI_frand() < (budget - (float)n))
+				n++;
+
+			for (i= 0; i < n; i++) {
+				get_random_point_on_triangle(v1, v2, v3, co);
+				add_meshlight(re, lcd, obr, vlr, co, weight);
+			}
+			
+			if (vlr->v4) {
+				/* XXX: check */
+				area= AreaT3Dfl(v1, v3, v4);
+				budget= area * density;
+				n= (int)(budget);
+				if (BLI_frand() < (budget - (float)n))
+					n++;
+
+				for (i= 0; i < n; i++) {
+					get_random_point_on_triangle(v1, v3, v4, co);
+					add_meshlight(re, lcd, obr, vlr, co, weight);
+				}	
+			} 
+		}
+	}
+}
+
 void lightcuts_init(Render * re)
 {
 	LightcutsData *lcd;
 	GroupObject *go;
 	ListBase *lights = &re->lights;
 	LampRen *lar, *own;
+	ObjectRen *obr;
 	char tree_time_str[12]; /* length 12 required by BLI_timestr */
-	int i, stop=0;
+	int i, stop=0, a;
 	
 	re->i.infostr= "Initializing Lightcuts";
 	re->stats_draw(&re->i);
@@ -1943,7 +2050,7 @@
 	else if (lcd->options & LC_OPT_ENV_LIGHT && re->r.lightcuts_env_map > 0)
 		R= *re;
 	
-	{
+	if (lcd->do_indir > 0 && lcd->options & LC_OPT_INDIR_MESH) {
 		int n_orig= 0;
 		int n_area= 0;
 		int n_vpl= 0;
@@ -1966,15 +2073,13 @@
 		if (lcd->options & LC_OPT_ENV_LIGHT)
 			n_generated+= re->r.lightcuts_env_map;
 		
-		if (lcd->do_indir > 0) {
-			n_vpl= (n_orig + n_generated) * lcd->do_indir * lcd->indir_bounces;
-			
-			/* allocate array to hold coordinates for all possible virtual point lights */
-			if (lcd->options & LC_OPT_INDIR_MESH && n_vpl != 0)
-				lcd->dbg_vis_vpl= MEM_callocN(sizeof(float) * 3 * n_vpl, "lc_vpl_visualization");
-			
-			n_generated+= n_vpl;
-		}
+		n_vpl= (n_orig + n_generated) * lcd->do_indir * lcd->indir_bounces;
+
+		/* allocate array to hold coordinates for all possible virtual point lights */
+		if (n_vpl != 0)
+			lcd->dbg_vis_vpl= MEM_callocN(sizeof(float) * 3 * n_vpl, "lc_vpl_visualization");
+
+		/* n_generated+= n_vpl; */
 	}
 	
 	/* TODO: we could do some form of importance sampling here */
@@ -1986,10 +2091,32 @@
 	}
 	lcd->area_density= re->r.lightcuts_area_lights / lcd->area_density;
 	
+	/* meshlights */
+	if (re->r.lightcuts_meshlights > 0) {
+		for(obr=re->objecttable.first; obr; obr=obr->next) {
+			for(a=0; a<obr->totvlak; a++) {
+				VlakRen *vlr= RE_findOrAddVlak(obr, a);
+				
+				if (vlr->mat && vlr->mat->emit != 0.0f) {
+					if (vlr->v4)
+						lcd->meshlights_density+= AreaQ3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co);
+					else
+						lcd->meshlights_density+= AreaT3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co); 
+				}
+			}
+		}
+		if (lcd->meshlights_density > 0.0f)
+			lcd->meshlights_density= re->r.lightcuts_meshlights / lcd->meshlights_density;
+		/* lcd->dbg_vis_vpl= MEM_callocN(sizeof(float) * 3 * re->r.lightcuts_meshlights, "lc_vpl_visualization"); */
+	}
+
 	/* light conversion */
 	
 	if (lcd->options & LC_OPT_ENV_LIGHT && re->r.lightcuts_env_map > 0)
 		convert_environment_map(re, lcd, re->r.lightcuts_env_map, re->r.lightcuts_env_map_fac);
+	
+	if (lcd->meshlights_density > 0.0f)
+		add_lights_from_mesh(lcd, re);
 
 	for(go=lights->first; go; go= go->next) {
 		lar= go->lampren;
@@ -2084,8 +2211,10 @@
 		lcd->vpl_to_cap= MEM_callocN(sizeof(int) * lcd->max_cut * re->r.threads, "vpl_to_cap");
 		
 		if (lcd->options & LC_OPT_INDIR_MESH && lcd->vpl_counter > 0)
-			dbg_create_vpl_mesh(re, lcd);
+			dbg_create_vis_mesh(re, lcd->vpl_counter, lcd->dbg_vis_vpl, "indir_visualize");
 	}
+	
+	/* dbg_create_vis_mesh(re, re->r.lightcuts_meshlights, lcd->dbg_vis_vpl, "meshlight_visualize"); */
 }
 
 /* Adapted from "Transforming Axis-Aligned Bounding Boxes" by Jim Arvo, "Graphics Gems", Academic Press, 1990 */

Modified: branches/soc-2008-unclezeiv/source/blender/src/buttons_scene.c
===================================================================
--- branches/soc-2008-unclezeiv/source/blender/src/buttons_scene.c	2008-10-22 20:30:02 UTC (rev 17185)
+++ branches/soc-2008-unclezeiv/source/blender/src/buttons_scene.c	2008-10-22 22:06:03 UTC (rev 17186)
@@ -3481,7 +3481,8 @@
 	uiDefButI(block, NUM, B_DIFF, "Max cut:", 97, -22, 95, 20, &G.scene->r.lightcuts_max_cut, 0, 5000, 0, 0, "The maximum size of the cut (higher values increase rendering times for occluded areas)");
 	uiBlockEndAlign(block);
 	
-	uiDefButI(block, NUM, B_DIFF, "Area lights:", 0, -54, 192, 20, &G.scene->r.lightcuts_area_lights, 0, 100000, 0, 0, "The number of point lights generated for all the area lights");
+	uiDefButI(block, NUM, B_DIFF, "Area lights:", 0, -54, 96, 20, &G.scene->r.lightcuts_area_lights, 0, 100000, 0, 0, "The number of point lights generated for all the area lights");
+	uiDefButI(block, NUM, B_DIFF, "Meshlights:", 96, -54, 96, 20, &G.scene->r.lightcuts_meshlights, 0, 100000, 0, 0, "The number of point lights generated for all the meshlights");
 
 	uiBlockBeginAlign(block);
 	uiDefButBitI(block, TOG, 0x8, B_DIFF, "Enable", 0, -86, 62, 20, &G.scene->r.lightcuts_options, 0, 0, 0, 0, "Enable environment map lighting");





More information about the Bf-blender-cvs mailing list