[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [25034] trunk/blender: Approximate AO: Diffuse Bounce Hack

Brecht Van Lommel brecht at blender.org
Mon Nov 30 19:42:15 CET 2009


Revision: 25034
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=25034
Author:   blendix
Date:     2009-11-30 19:42:13 +0100 (Mon, 30 Nov 2009)

Log Message:
-----------
Approximate AO: Diffuse Bounce Hack

This brings back the single bounce indirect diffuse lighting for AAO,
it's not integrated well but that will be tackled later as part of
shading system refactor and subdivision changes. The caveats are the
same as AAO, with one extra thing, the diffuse lighting is sampled once
per face, so it will not be accurate unless faces are subdivided.

I'm committing this now so we can start testing it for Durian, and
since changes need to make it work properly are planned.

Modified Paths:
--------------
    trunk/blender/release/scripts/ui/properties_world.py
    trunk/blender/source/blender/makesdna/DNA_world_types.h
    trunk/blender/source/blender/makesrna/intern/rna_world.c
    trunk/blender/source/blender/render/extern/include/RE_shader_ext.h
    trunk/blender/source/blender/render/intern/include/render_types.h
    trunk/blender/source/blender/render/intern/source/occlusion.c
    trunk/blender/source/blender/render/intern/source/shadeoutput.c
    trunk/blender/source/blender/render/intern/source/strand.c

Modified: trunk/blender/release/scripts/ui/properties_world.py
===================================================================
--- trunk/blender/release/scripts/ui/properties_world.py	2009-11-30 18:26:53 UTC (rev 25033)
+++ trunk/blender/release/scripts/ui/properties_world.py	2009-11-30 18:42:13 UTC (rev 25034)
@@ -219,6 +219,7 @@
 
         col = split.column()
         col.prop(ao, "energy")
+        col.prop(ao, "indirect_energy")
 
         if wide_ui:
             col = split.column()

Modified: trunk/blender/source/blender/makesdna/DNA_world_types.h
===================================================================
--- trunk/blender/source/blender/makesdna/DNA_world_types.h	2009-11-30 18:26:53 UTC (rev 25033)
+++ trunk/blender/source/blender/makesdna/DNA_world_types.h	2009-11-30 18:42:13 UTC (rev 25034)
@@ -107,6 +107,7 @@
 	short aomode, aosamp, aomix, aocolor;
 	float ao_adapt_thresh, ao_adapt_speed_fac;
 	float ao_approx_error, ao_approx_correction;
+	float ao_indirect_energy, aopad;
 	short ao_samp_method, ao_gather_method, ao_approx_passes;
 	
 	/* assorted settings (in the middle of ambient occlusion settings for padding reasons) */

Modified: trunk/blender/source/blender/makesrna/intern/rna_world.c
===================================================================
--- trunk/blender/source/blender/makesrna/intern/rna_world.c	2009-11-30 18:26:53 UTC (rev 25033)
+++ trunk/blender/source/blender/makesrna/intern/rna_world.c	2009-11-30 18:42:13 UTC (rev 25034)
@@ -312,6 +312,12 @@
 	RNA_def_property_range(prop, 0, 10);
 	RNA_def_property_ui_text(prop, "Passes", "Number of preprocessing passes to reduce overocclusion (for Approximate).");
 	RNA_def_property_update(prop, 0, "rna_World_update");
+
+	prop= RNA_def_property(srna, "indirect_energy", PROP_FLOAT, PROP_UNSIGNED);
+	RNA_def_property_float_sdna(prop, NULL, "ao_indirect_energy");
+	RNA_def_property_ui_range(prop, 0, 10, 0.1, 3);
+	RNA_def_property_ui_text(prop, "Indirect", "Use approximate ambient occlusion for indirect diffuse lighting.");
+	RNA_def_property_update(prop, 0, "rna_World_update");
 }
 
 static void rna_def_world_mist(BlenderRNA *brna)

Modified: trunk/blender/source/blender/render/extern/include/RE_shader_ext.h
===================================================================
--- trunk/blender/source/blender/render/extern/include/RE_shader_ext.h	2009-11-30 18:26:53 UTC (rev 25033)
+++ trunk/blender/source/blender/render/extern/include/RE_shader_ext.h	2009-11-30 18:42:13 UTC (rev 25034)
@@ -153,7 +153,7 @@
 	float dxstrand, dystrand;
 	
 	/* AO is a pre-process now */
-	float ao[3];
+	float ao[3], indirect[3];
 	
 	int xs, ys;				/* pixel to be rendered */
 	int mask;				/* subsample mask */

Modified: trunk/blender/source/blender/render/intern/include/render_types.h
===================================================================
--- trunk/blender/source/blender/render/intern/include/render_types.h	2009-11-30 18:26:53 UTC (rev 25033)
+++ trunk/blender/source/blender/render/intern/include/render_types.h	2009-11-30 18:42:13 UTC (rev 25034)
@@ -398,7 +398,8 @@
 	int (*face)[4];
 	float (*co)[3];
 	/* for occlusion caching */
-	float (*col)[3];
+	float (*ao)[3];
+	float (*indirect)[3];
 	/* for speedvectors */
 	float (*prevco)[3], (*nextco)[3];
 	int totvert, totface;

Modified: trunk/blender/source/blender/render/intern/source/occlusion.c
===================================================================
--- trunk/blender/source/blender/render/intern/source/occlusion.c	2009-11-30 18:26:53 UTC (rev 25033)
+++ trunk/blender/source/blender/render/intern/source/occlusion.c	2009-11-30 18:42:13 UTC (rev 25034)
@@ -64,7 +64,7 @@
 #define CACHE_STEP 3
 
 typedef struct OcclusionCacheSample {
-	float co[3], n[3], col[3], intensity, dist2;
+	float co[3], n[3], ao[3], indirect[3], intensity, dist2;
 	int x, y, filled;
 } OcclusionCacheSample;
 
@@ -81,7 +81,7 @@
 typedef struct OccNode {
 	float co[3], area;
 	float sh[9], dco;
-	float occlusion;
+	float occlusion, rad[3];
 	int childflag;
 	union {
 		//OccFace face;
@@ -97,6 +97,7 @@
 
 	OccFace *face;		/* instance and face indices */
 	float *occlusion;	/* occlusion for faces */
+	float (*rad)[3];	/* radiance for faces */
 	
 	OccNode *root;
 
@@ -117,7 +118,8 @@
 typedef struct OcclusionThread {
 	Render *re;
 	StrandSurface *mesh;
-	float (*facecol)[3];
+	float (*faceao)[3];
+	float (*faceindirect)[3];
 	int begin, end;
 	int thread;
 } OcclusionThread;
@@ -132,7 +134,6 @@
 
 extern Render R; // meh
 
-#if 0
 static void occ_shade(ShadeSample *ssamp, ObjectInstanceRen *obi, VlakRen *vlr, float *rad)
 {
 	ShadeInput *shi= ssamp->shi;
@@ -160,7 +161,7 @@
 	shi->co[0]= l*v3[0]+u*v1[0]+v*v2[0];
 	shi->co[1]= l*v3[1]+u*v1[1]+v*v2[1];
 	shi->co[2]= l*v3[2]+u*v1[2]+v*v2[2];
-	
+
 	shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);
 
 	/* set up view vector */
@@ -179,6 +180,8 @@
 	if(shi->flippednor)
 		shade_input_flip_normals(shi);
 
+	madd_v3_v3fl(shi->co, shi->vn, 0.0001f); /* ugly.. */
+
 	/* not a pretty solution, but fixes common cases */
 	if(shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) {
 		negate_v3(shi->vn);
@@ -215,12 +218,11 @@
 
 	for(a=0; a<tree->totface; a++) {
 		obi= &R.objectinstance[tree->face[a].obi];
-		vlr= RE_findOrAddVlak(obi->obr, tree->face[a].vlr);
+		vlr= RE_findOrAddVlak(obi->obr, tree->face[a].facenr);
 
 		occ_shade(&ssamp, obi, vlr, tree->rad[a]);
 	}
 }
-#endif
 
 /* ------------------------- Spherical Harmonics --------------------------- */
 
@@ -352,17 +354,19 @@
 static void occ_sum_occlusion(OcclusionTree *tree, OccNode *node)
 {
 	OccNode *child;
-	float occ, area, totarea;
+	float occ, area, totarea, rad[3];
 	int a, b;
 
 	occ= 0.0f;
 	totarea= 0.0f;
+	zero_v3(rad);
 
 	for(b=0; b<TOTCHILD; b++) {
 		if(node->childflag & (1<<b)) {
 			a= node->child[b].face;
 			occ_face(&tree->face[a], 0, 0, &area);
 			occ += area*tree->occlusion[a];
+			madd_v3_v3fl(rad, tree->rad[a], area);
 			totarea += area;
 		}
 		else if(node->child[b].node) {
@@ -370,14 +374,18 @@
 			occ_sum_occlusion(tree, child);
 
 			occ += child->area*child->occlusion;
+			madd_v3_v3fl(rad, child->rad, child->area);
 			totarea += child->area;
 		}
 	}
 
-	if(totarea != 0.0f)
+	if(totarea != 0.0f) {
 		occ /= totarea;
+		mul_v3_fl(rad, 1.0f/totarea);
+	}
 	
 	node->occlusion= occ;
+	copy_v3_v3(node->rad, rad);
 }
 
 static int occ_find_bbox_axis(OcclusionTree *tree, int begin, int end, float *min, float *max)
@@ -656,6 +664,9 @@
 	tree->co= MEM_callocN(sizeof(float)*3*totface, "OcclusionCo");
 	tree->occlusion= MEM_callocN(sizeof(float)*totface, "OcclusionOcclusion");
 
+	if(re->wrld.ao_indirect_energy != 0.0f)
+		tree->rad= MEM_callocN(sizeof(float)*3*totface, "OcclusionRad");
+
 	/* make array of face pointers */
 	for(b=0, c=0, obi=re->instancetable.first; obi; obi=obi->next, c++) {
 		obr= obi->obr;
@@ -682,12 +693,10 @@
 	tree->maxdepth= 1;
 	occ_build_recursive(tree, tree->root, 0, totface, 1);
 
-#if 0
-	if(tree->doindirect) {
+	if(re->wrld.ao_indirect_energy != 0.0f) {
 		occ_build_shade(re, tree);
 		occ_sum_occlusion(tree, tree->root);
 	}
-#endif
 	
 	MEM_freeN(tree->co);
 	tree->co= NULL;
@@ -710,8 +719,9 @@
 			if(tree->stack[a])
 				MEM_freeN(tree->stack[a]);
 		if(tree->occlusion) MEM_freeN(tree->occlusion);
+		if(tree->cache) MEM_freeN(tree->cache);
 		if(tree->face) MEM_freeN(tree->face);
-		if(tree->cache) MEM_freeN(tree->cache);
+		if(tree->rad) MEM_freeN(tree->rad);
 		MEM_freeN(tree);
 	}
 }
@@ -1171,13 +1181,13 @@
 	return contrib;
 }
 
-static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float *pp, float *pn, float *occ, float *bentn)
+static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float *pp, float *pn, float *occ, float rad[3], float bentn[3])
 {
 	OccNode *node, **stack;
 	OccFace *face;
-	float resultocc, v[3], p[3], n[3], co[3], invd2;
+	float resultocc, resultrad[3], v[3], p[3], n[3], co[3], invd2;
 	float distfac, fac, error, d2, weight, emitarea;
-	int b, totstack;
+	int b, f, totstack;
 
 	/* init variables */
 	VECCOPY(p, pp);
@@ -1185,12 +1195,13 @@
 	VECADDFAC(p, p, n, 1e-4f);
 
 	if(bentn)
-		VECCOPY(bentn, n);
+		copy_v3_v3(bentn, n);
 	
 	error= tree->error;
 	distfac= tree->distfac;
 
 	resultocc= 0.0f;
+	zero_v3(resultrad);
 
 	/* init stack */
 	stack= tree->stack[thread];
@@ -1217,6 +1228,10 @@
 			/* accumulate occlusion from spherical harmonics */
 			invd2 = 1.0f/sqrtf(d2);
 			weight= occ_solid_angle(node, v, d2, invd2, n);
+
+			if(rad)
+				madd_v3_v3fl(resultrad, node->rad, weight*fac);
+
 			weight *= node->occlusion;
 
 			if(bentn) {
@@ -1231,7 +1246,8 @@
 			/* traverse into children */
 			for(b=0; b<TOTCHILD; b++) {
 				if(node->childflag & (1<<b)) {
-					face= tree->face+node->child[b].face;
+					f= node->child[b].face;
+					face= &tree->face[f];
 
 					/* accumulate occlusion with face form factor */
 					if(!exclude || !(face->obi == exclude->obi && face->facenr == exclude->facenr)) {
@@ -1248,8 +1264,12 @@
 							fac= 1.0f;
 
 						weight= occ_form_factor(face, p, n);
-						weight *= tree->occlusion[node->child[b].face];
 
+						if(rad)
+							madd_v3_v3fl(resultrad, tree->rad[f], weight*fac);
+
+						weight *= tree->occlusion[f];
+
 						if(bentn) {
 							invd2= 1.0f/sqrtf(d2);
 							bentn[0] -= weight*invd2*v[0];
@@ -1269,15 +1289,24 @@
 	}
 
 	if(occ) *occ= resultocc;
+	if(rad) copy_v3_v3(rad, resultrad);
+	/*if(rad && exclude) {
+		int a;
+		for(a=0; a<tree->totface; a++)
+			if((tree->face[a].obi == exclude->obi && tree->face[a].facenr == exclude->facenr))
+				copy_v3_v3(rad, tree->rad[a]);
+	}*/
 	if(bentn) normalize_v3(bentn);
 }
 
 static void occ_compute_passes(Render *re, OcclusionTree *tree, int totpass)
 {
-	float *occ, co[3], n[3];
+	float *occ, (*rad)[3]= NULL, co[3], n[3];
 	int pass, i;
 	
 	occ= MEM_callocN(sizeof(float)*tree->totface, "OcclusionPassOcc");
+	if(tree->rad)
+		rad= MEM_callocN(sizeof(float)*3*tree->totface, "OcclusionPassRad");
 
 	for(pass=0; pass<totpass; pass++) {
 		for(i=0; i<tree->totface; i++) {
@@ -1285,7 +1314,7 @@
 			negate_v3(n);
 			VECADDFAC(co, co, n, 1e-8f);
 
-			occ_lookup(tree, 0, &tree->face[i], co, n, &occ[i], NULL);
+			occ_lookup(tree, 0, &tree->face[i], co, n, &occ[i], NULL, (rad)? rad[i]: NULL);
 			if(re->test_break(re->tbh))
 				break;
 		}
@@ -1297,27 +1326,41 @@
 			tree->occlusion[i] -= occ[i]; //MAX2(1.0f-occ[i], 0.0f);
 			if(tree->occlusion[i] < 0.0f)
 				tree->occlusion[i]= 0.0f;
+
+			if(rad) {
+				sub_v3_v3(tree->rad[i], rad[i]);
+

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list