[Bf-committers] Multiple Ligth Scattering buggs correction (Farsthary)

Raul Fernandez Hernandez raulf at info.upr.edu.cu
Sat Jan 2 20:19:28 CET 2010


Hi all :)

 Congratullations and Happy New Year!

  I spend the whole day yesterday fixing old buggs in the volumetric code
regarding Multiple Ligth Scattering since it was not behaving as should
do.

I also have made a few performance improvements to the code, like for
example, in many places where appears multiple calls to the indexing
functions V_I() in the same scope , calculating it once and stored in a
variable and then call it when needed, it saves some multiplications :)

 I have sended the patch to Matt Ebb for review and commit, it should not
be very difficult to apply, in case someone want to take a look at it I
attach it at the end of this mail.

 Here's a summary of the squashed buggs ;) :

   - they where a non correspondence between the LC and the MLS buffers,
they follow a different alligment that lead to incorrect fill process
if use a single indexing function for both. (I have corrected the
indexing in the MLS buffers)

   - The actual diffussion process where something like ...
      x[]=x0[]+a(x[]+x[]+...)/(1+6*a)
    where should be
      x[]=x0[]+a(x0[]+x0[]+...)/(1+6*a)
   each simulation step is only dependant on previous step or buffer.

   - The MLS buffer where not initialized and filled with the single
scattering pass before the actual simulation start, in the
shade_one_lamp() only the single scattering trigger the LC calculation,
where should be triggered also in the Multiple scattering and the
shaded+Multiple scattering cases. The MLS should start from the single
scattering filled ligth cache.

   - the Multiple scattering was called after the filtering function calls
where should be called BEFORE, because the filtering function may
introduce artifacts that later will get amplified in the MLS simulation
process.

And finally, this is not a bug but a correction: the diffussion parametter
is in range 0.0 to FLOAT_MAX , where it only have sense in the range
0.0-1.0, higher values than 1.0 have no effect,does not increase the
diffussion:

  in file rna_material.c

	prop= RNA_def_property(srna, "ms_diffusion", PROP_FLOAT, PROP_NONE);
	RNA_def_property_float_sdna(prop, NULL, "ms_diff");
--      RNA_def_property_range(prop, 0.0f, FLT_MAX);
++	RNA_def_property_range(prop, 0.0f, 1.0f);
	RNA_def_property_ui_text(prop, "Diffusion", "Diffusion factor, the
strength of the blurring

effect");
	RNA_def_property_update(prop, 0, "rna_Material_update");

----------- here's the complete diff patch ------------------------------

diff -r /home/raul/Escritorio/Previous/volume_precache.c
/home/raul/Escritorio/Modified/volume_precache.c
24c24
<  * Contributor(s): Matt Ebb.
---
>  * Contributor(s): Matt Ebb, Raúl Fernández Hernández (Farsthary).
137,139c137,139
<
< 							if (cache[ V_I(x_, y_, z_, res) ] > 0.0f) {
< 								tot += cache[ V_I(x_, y_, z_, res) ];
---
> 						        int i= V_I(x_, y_, z_, res) ;
> 							if (cache[i] > 0.0f) {
> 								tot += cache[i];
167,172c167,173
< 				if (vp->data_r[ V_I(x, y, z, vp->res) ] < -0.f)
< 					vp->data_r[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_r,
vp->res, x, y, z);
< 				if (vp->data_g[ V_I(x, y, z, vp->res) ] < -0.f)
< 					vp->data_g[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_g,
vp->res, x, y, z);
< 				if (vp->data_b[ V_I(x, y, z, vp->res) ] < -0.f)
< 					vp->data_b[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_b,
vp->res, x, y, z);
---
> 				int i= V_I(x, y, z, vp->res);
> 				if (vp->data_r[i] < -0.f)
> 					vp->data_r[i] = get_avg_surrounds(vp->data_r, vp->res, x, y, z);
> 				if (vp->data_g[i] < -0.f)
> 					vp->data_g[i] = get_avg_surrounds(vp->data_g, vp->res, x, y, z);
> 				if (vp->data_b[i] < -0.f)
> 					vp->data_b[i] = get_avg_surrounds(vp->data_b, vp->res, x, y, z);
175c176
< 	}
---
> 	}
181c182
< 	int x, y, z;
---
> 	int x, y, z;
197,202c198,204
< 				if (vp->data_r[ V_I(x, y, z, vp->res) ] < -0.f)
< 					new_r[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_r,
vp->res, x, y, z);
< 				if (vp->data_g[ V_I(x, y, z, vp->res) ] < -0.f)
< 					new_g[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_g,
vp->res, x, y, z);
< 				if (vp->data_b[ V_I(x, y, z, vp->res) ] < -0.f)
< 					new_b[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_b,
vp->res, x, y, z);
---
> 				int i= V_I(x, y, z, vp->res);
> 				if (vp->data_r[i] < -0.f)
> 					new_r[i] = get_avg_surrounds(vp->data_r, vp->res, x, y, z);
> 				if (vp->data_g[i] < -0.f)
> 					new_g[i] = get_avg_surrounds(vp->data_g, vp->res, x, y, z);
> 				if (vp->data_b[i] < -0.f)
> 					new_b[i] = get_avg_surrounds(vp->data_b, vp->res, x, y, z);
213c215
< 	if (new_b) { MEM_freeN(new_b); new_b=NULL; }
---
> 	if (new_b) { MEM_freeN(new_b); new_b=NULL; }
216a219
> /* Is very important to watch the order of the voxel array */
219c222,227
< 	return z*(n[1]+2)*(n[0]+2) + y*(n[0]+2) + x;
---
> 	return z*(n[1]+2)*(n[0]+2) + y*(n[0]+2) + x;
> }
>
> static inline int _I(int x, int y, int z, int *n) //has a pad of 1 voxel
surrounding the core for boundary simulation
> {
> 	return x*(n[1]+2)*(n[2]+2) + y*(n[2]+2) + z; }
226c234
< static float total_ss_energy(VolumePrecache *vp)
---
> static float total_ss_energy(VolumePrecache *vp)
235,237c243,247
< 				if (vp->data_r[ V_I(x, y, z, res) ] > 0.f) energy += vp->data_r[
V_I(x, y, z, res) ];
< 				if (vp->data_g[ V_I(x, y, z, res) ] > 0.f) energy += vp->data_g[
V_I(x, y, z, res) ];
< 				if (vp->data_b[ V_I(x, y, z, res) ] > 0.f) energy += vp->data_b[
V_I(x, y, z, res) ];
---
> 			        int i=V_I(x, y, z, res);
>
> 				if (vp->data_r[i] > 0.f) energy += vp->data_r[i];
> 				if (vp->data_g[i] > 0.f) energy += vp->data_g[i];
> 				if (vp->data_b[i] > 0.f) energy += vp->data_b[i];
254c264
< 				i = ms_I(x,y,z,res);
---
> 				i = _I(x,y,z,res);
265c275
< static void ms_diffuse(int b, float* x0, float* x, float diff, int *n)
---
> static void ms_diffuse(float* x0, float* x, float diff, int *n) //n is
the unpadded resolution
270,271c280,281
<
< 	for (l=0; l<20; l++)
---
>
> 	for (l=0; l<20; l++)
279,282c289
< 					x[ms_I(i,j,k,n)] = (x0[ms_I(i,j,k,n)] + a*(
< 						 x[ms_I(i-1,j,k,n)]+x[ms_I(i+1,j,k,n)]+
< 						 x[ms_I(i,j-1,k,n)]+x[ms_I(i,j+1,k,n)]+
< 						 x[ms_I(i,j,k-1,n)]+x[ms_I(i,j,k+1,n)]))/(1+6*a);
---
> 				   x[ms_I(i,j,k,n)] = (x0[ms_I(i,j,k,n)]) + a*(
x0[ms_I(i-1,j,k,n)]+x0[ms_I(i+1,j,k,n)]+
x0[ms_I(i,j-1,k,n)]+x0[ms_I(i,j+1,k,n)]+
x0[ms_I(i,j,k-1,n)]+x0[ms_I(i,j,k+1,n)] )/(1+6*a);
327c334,336
< 					i = V_I((x-1), (y-1), (z-1), n);
---
> 				        i=(x-1)*n[1]*n[2] + (y-1)*n[2] + z-1; //lc index
> 					int j=_I(x,y,z,n); //ms index
>
329,336c338,344
< 					c++;
<
< 					if (vp->data_r[i] > 0.f)
< 						sr[ms_I(x,y,z,n)] += vp->data_r[i];
< 					if (vp->data_g[i] > 0.f)
< 						sg[ms_I(x,y,z,n)] += vp->data_g[i];
< 					if (vp->data_b[i] > 0.f)
< 						sb[ms_I(x,y,z,n)] += vp->data_b[i];
---
> 					c++;
> 					if (vp->data_r[i] > 0.0f)
> 						sr[j] += vp->data_r[i];
> 					if (vp->data_g[i] > 0.0f)
> 						sg[j] += vp->data_g[i];
> 					if (vp->data_b[i] > 0.0f)
> 						sb[j] += vp->data_b[i];
341,342c349
< 						sprintf(str, "Simulating multiple scattering: %d%%", (int)
< 								(100.0f * (c / total)));
---
> 						sprintf(str, "Simulating multiple scattering: %d%%", (int)(100.0f
* (c / total)));
351,358c358,365
< 		SWAP(float *, sr, sr0);
< 		SWAP(float *, sg, sg0);
< 		SWAP(float *, sb, sb0);
<
< 		/* main diffusion simulation */
< 		ms_diffuse(0, sr0, sr, diff, n);
< 		ms_diffuse(0, sg0, sg, diff, n);
< 		ms_diffuse(0, sb0, sb, diff, n);
---
> 		SWAP(float *,sr,sr0);
> 		SWAP(float *,sg,sg0);
> 		SWAP(float *,sb,sb0);
>
> 	      	/* main diffusion simulation */
> 		ms_diffuse(sr0, sr, diff, n);
> 		ms_diffuse(sg0, sg, diff, n);
> 		ms_diffuse(sb0, sb, diff, n);
374c381,382
< 	}
---
>
> 	}
375a384
>
382,385c391,396
< 				int index=(x-1)*n[1]*n[2] + (y-1)*n[2] + z-1;
< 				vp->data_r[index] = origf * vp->data_r[index] + fac *
sr[ms_I(x,y,z,n)];
< 				vp->data_g[index] = origf * vp->data_g[index] + fac *
sg[ms_I(x,y,z,n)];
< 				vp->data_b[index] = origf * vp->data_b[index] + fac *
sb[ms_I(x,y,z,n)];
---
> 				int index=(x-1)*n[1]*n[2] + (y-1)*n[2] + z-1; //lc index
> 				int j=_I(x,y,z,n);                            //ms index
>
> 				vp->data_r[index] = origf * vp->data_r[index] + fac * sr[j];
> 				vp->data_g[index] = origf * vp->data_g[index] + fac * sg[j];
> 				vp->data_b[index] = origf * vp->data_b[index] + fac * sb[j];
395c406
< 	MEM_freeN(sb);
---
> 	MEM_freeN(sb);
429c440
< 	int x, y, z;
---
> 	int x, y, z, i;
440c451,452
<
---
>
> 				i=V_I(x, y, z, res);  //lc index
443,445c455,457
< 					obi->volume_precache->data_r[ V_I(x, y, z, res) ] = -1.0f;
< 					obi->volume_precache->data_g[ V_I(x, y, z, res) ] = -1.0f;
< 					obi->volume_precache->data_b[ V_I(x, y, z, res) ] = -1.0f;
---
> 					obi->volume_precache->data_r[i] = -1.0f;
> 					obi->volume_precache->data_g[i] = -1.0f;
> 					obi->volume_precache->data_b[i] = -1.0f;
453,455c465,467
< 				obi->volume_precache->data_r[ V_I(x, y, z, res) ] = scatter_col[0];
< 				obi->volume_precache->data_g[ V_I(x, y, z, res) ] = scatter_col[1];
< 				obi->volume_precache->data_b[ V_I(x, y, z, res) ] = scatter_col[2];
---
> 				obi->volume_precache->data_r[i] = scatter_col[0];
> 				obi->volume_precache->data_g[i] = scatter_col[1];
> 				obi->volume_precache->data_b[i] = scatter_col[2];
675c687,688
< 		}
---
> 		}
>
679c692
< 	BLI_freelistN(&re->volume_precache_parts);
---
> 	BLI_freelistN(&re->volume_precache_parts);
687,689c700
< 	lightcache_filter(obi->volume_precache);
<
< 	if (ELEM(ma->vol.shade_type, MA_VOL_SHADE_MULTIPLE,
MA_VOL_SHADE_SHADEDPLUSMULTIPLE))
---
> 	if (ELEM(ma->vol.shade_type, MA_VOL_SHADE_MULTIPLE,
MA_VOL_SHADE_SHADEDPLUSMULTIPLE)) //this should be before the filtering
691c702
< 		multiple_scattering_diffusion(re, vp, ma);
---
> 		multiple_scattering_diffusion(re, obi->volume_precache, ma);
692a704,706
>
> 	lightcache_filter(obi->volume_precache);
>
712c726
< 					vol_precache_objectinstance_threads(re, obi, vo->ma);
---
> 				vol_precache_objectinstance_threads(re, obi, vo->ma);
diff -r /home/raul/Escritorio/Previous/volumetric.c
/home/raul/Escritorio/Modified/volumetric.c
495,496c495,496
< 	}
< 	else if (shi->mat->vol.shade_type == MA_VOL_SHADE_SHADED)
---
> 	} /* the base for Multiple scattering simulation are single scattering*/
> 	else if (shi->mat->vol.shade_type == MA_VOL_SHADE_SHADED ||
shi->mat->vol.shade_type == MA_VOL_SHADE_MULTIPLE ||
shi->mat->vol.shade_type == MA_VOL_SHADE_SHADEDPLUSMULTIPLE)
516,517c516
< 			if (ELEM(lar->type, LA_SUN, LA_HEMI))
< 				/* infinite lights, can never be inside volume */
---
> 			if (ELEM(lar->type, LA_SUN, LA_HEMI)) 	/* infinite lights, can never
be inside volume */
632c631,632
< 			radiance[2] += stepd * tr[2] * (emit_col[2] + scatter_col[2]);
---
> 			radiance[2] += stepd * tr[2] * (emit_col[2] + scatter_col[2]);
>
640c640
<
---
>
642c642
< 	col[3] = 1.0f - luminance(tr);
---
> 	col[3] = 1.0f - luminance(tr);




More information about the Bf-committers mailing list