[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [16960] trunk/blender/source/blender/ render: Fix for bug #13363: ray (qmc) shadows had some light leaking issues ,

Brecht Van Lommel brecht at blender.org
Tue Oct 7 17:01:44 CEST 2008


Revision: 16960
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=16960
Author:   blendix
Date:     2008-10-07 17:01:44 +0200 (Tue, 07 Oct 2008)

Log Message:
-----------
Fix for bug #13363: ray (qmc) shadows had some light leaking issues,
due to jittering of the start position for antialiasing in a pixel.

Now it distributes the start position over the fixed osa sample
positions, instead of of random positions in space. The ugly bit is
that a custom ordering was defined for osa 8/11/16 to ensure that the
first 4 are distributed relatively fair for adaptive sampling to decide
if more samples need to be taken.

Modified Paths:
--------------
    trunk/blender/source/blender/render/extern/include/RE_shader_ext.h
    trunk/blender/source/blender/render/intern/include/shading.h
    trunk/blender/source/blender/render/intern/source/rayshade.c
    trunk/blender/source/blender/render/intern/source/rendercore.c
    trunk/blender/source/blender/render/intern/source/shadeinput.c
    trunk/blender/source/blender/render/intern/source/zbuf.c

Modified: trunk/blender/source/blender/render/extern/include/RE_shader_ext.h
===================================================================
--- trunk/blender/source/blender/render/extern/include/RE_shader_ext.h	2008-10-07 14:24:08 UTC (rev 16959)
+++ trunk/blender/source/blender/render/extern/include/RE_shader_ext.h	2008-10-07 15:01:44 UTC (rev 16960)
@@ -157,6 +157,7 @@
 	
 	int xs, ys;				/* pixel to be rendered */
 	int mask;				/* subsample mask */
+	float scanco[3];		/* original scanline coordinate without jitter */
 	
 	int samplenr;			/* sample counter, to detect if we should do shadow again */
 	int depth;				/* 1 or larger on raytrace shading */

Modified: trunk/blender/source/blender/render/intern/include/shading.h
===================================================================
--- trunk/blender/source/blender/render/intern/include/shading.h	2008-10-07 14:24:08 UTC (rev 16959)
+++ trunk/blender/source/blender/render/intern/include/shading.h	2008-10-07 15:01:44 UTC (rev 16960)
@@ -56,7 +56,8 @@
 void shade_input_set_triangle_i(struct ShadeInput *shi, struct ObjectInstanceRen *obi, struct VlakRen *vlr, short i1, short i2, short i3);
 void shade_input_set_triangle(struct ShadeInput *shi, volatile int obi, volatile int facenr, int normal_flip);
 void shade_input_copy_triangle(struct ShadeInput *shi, struct ShadeInput *from);
-void shade_input_set_viewco(struct ShadeInput *shi, float x, float y, float z);
+void shade_input_calc_viewco(struct ShadeInput *shi, float x, float y, float z, float *view, float *dxyview, float *co, float *dxco, float *dyco);
+void shade_input_set_viewco(struct ShadeInput *shi, float x, float y, float sx, float sy, float z);
 void shade_input_set_uv(struct ShadeInput *shi);
 void shade_input_set_normals(struct ShadeInput *shi);
 void shade_input_flip_normals(struct ShadeInput *shi);

Modified: trunk/blender/source/blender/render/intern/source/rayshade.c
===================================================================
--- trunk/blender/source/blender/render/intern/source/rayshade.c	2008-10-07 14:24:08 UTC (rev 16959)
+++ trunk/blender/source/blender/render/intern/source/rayshade.c	2008-10-07 15:01:44 UTC (rev 16960)
@@ -1792,21 +1792,62 @@
 		ray_ao_spheresamp(shi, shadfac);
 }
 
+static void ray_shadow_jittered_coords(ShadeInput *shi, int max, float jitco[RE_MAX_OSA][3], int *totjitco)
+{
+	/* magic numbers for reordering sample positions to give better
+	 * results with adaptive sample, when it usually only takes 4 samples */
+	int order8[8] = {0, 1, 5, 6, 2, 3, 4, 7};
+	int order11[11] = {1, 3, 8, 10, 0, 2, 4, 5, 6, 7, 9};
+	int order16[16] = {1, 3, 9, 12, 0, 6, 7, 8, 13, 2, 4, 5, 10, 11, 14, 15};
+	int count = count_mask(shi->mask);
 
+	/* for better antialising shadow samples are distributed over the subpixel
+	 * sample coordinates, this only works for raytracing depth 0 though */
+	if(!shi->strand && shi->depth == 0 && count > 1 && count <= max) {
+		float xs, ys, zs, view[3];
+		int samp, ordsamp, tot= 0;
+
+		for(samp=0; samp<R.osa; samp++) {
+			if(R.osa == 8) ordsamp = order8[samp];
+			else if(R.osa == 11) ordsamp = order11[samp];
+			else if(R.osa == 16) ordsamp = order16[samp];
+			else ordsamp = samp;
+
+			if(shi->mask & (1<<ordsamp)) {
+				/* zbuffer has this inverse corrected, ensures xs,ys are inside pixel */
+				xs= (float)shi->scanco[0] + R.jit[ordsamp][0] + 0.5f;
+				ys= (float)shi->scanco[1] + R.jit[ordsamp][1] + 0.5f;
+				zs= shi->scanco[2];
+
+				shade_input_calc_viewco(shi, xs, ys, zs, view, NULL, jitco[tot], NULL, NULL);
+				tot++;
+			}
+		}
+
+		*totjitco= tot;
+	}
+	else {
+		VECCOPY(jitco[0], shi->co);
+		*totjitco= 1;
+	}
+}
+
 static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *shadfac, Isect *isec)
 {
 	QMCSampler *qsa=NULL;
-	QMCSampler *qsa_jit=NULL;
 	int samples=0;
-	float samp3d[3], jit[3], jitbias= 0.0f;
+	float samp3d[3];
 
 	float fac=0.0f, vec[3];
 	float colsq[4];
 	float adapt_thresh = lar->adapt_thresh;
-	int max_samples = lar->ray_totsamp;
-	float pos[3];
+	int min_adapt_samples=4, max_samples = lar->ray_totsamp;
+	float *co;
 	int do_soft=1, full_osa=0;
 
+	float jitco[RE_MAX_OSA][3];
+	int totjitco;
+
 	colsq[0] = colsq[1] = colsq[2] = 0.0;
 	if(isec->mode==RE_RAY_SHADOW_TRA) {
 		shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 0.0f;
@@ -1823,21 +1864,16 @@
 		if (do_soft) max_samples = lar->ray_totsamp;
 		else max_samples = (R.osa > 4)?R.osa:5;
 	}
+	
+	ray_shadow_jittered_coords(shi, max_samples, jitco, &totjitco);
 
-	if(shi->vlr && ((shi->vlr->flag & R_FULL_OSA) == 0))
-		jitbias= 0.5f*(VecLength(shi->dxco) + VecLength(shi->dyco));
-
 	/* sampling init */
-	if (lar->ray_samp_method==LA_SAMP_HALTON) {
+	if (lar->ray_samp_method==LA_SAMP_HALTON)
 		qsa = get_thread_qmcsampler(&R, shi->thread, SAMP_TYPE_HALTON, max_samples);
-		qsa_jit = get_thread_qmcsampler(&R, shi->thread, SAMP_TYPE_HALTON, max_samples);
-	} else if (lar->ray_samp_method==LA_SAMP_HAMMERSLEY) {
+	else if (lar->ray_samp_method==LA_SAMP_HAMMERSLEY)
 		qsa = get_thread_qmcsampler(&R, shi->thread, SAMP_TYPE_HAMMERSLEY, max_samples);
-		qsa_jit = get_thread_qmcsampler(&R, shi->thread, SAMP_TYPE_HAMMERSLEY, max_samples);
-	}
 	
 	QMC_initPixel(qsa, shi->thread);
-	QMC_initPixel(qsa_jit, shi->thread);
 	
 	VECCOPY(vec, lampco);
 	
@@ -1845,18 +1881,11 @@
 	while (samples < max_samples) {
 		isec->faceorig= (RayFace*)shi->vlr;
 		isec->oborig= RAY_OBJECT_SET(&R, shi->obi);
-		
+
 		/* manually jitter the start shading co-ord per sample
 		 * based on the pre-generated OSA texture sampling offsets, 
 		 * for anti-aliasing sharp shadow edges. */
-		VECCOPY(pos, shi->co);
-		if (shi->vlr && !full_osa) {
-			QMC_sampleRect(jit, qsa_jit, shi->thread, samples, 1.0, 1.0);
-			
-			pos[0] += shi->dxco[0]*jit[0] + shi->dyco[0]*jit[1];
-			pos[1] += shi->dxco[1]*jit[0] + shi->dyco[1]*jit[1];
-			pos[2] += shi->dxco[2]*jit[0] + shi->dyco[2]*jit[1];
-		}
+		co = jitco[samples % totjitco];
 
 		if (do_soft) {
 			/* sphere shadow source */
@@ -1864,9 +1893,9 @@
 				float ru[3], rv[3], v[3], s[3];
 				
 				/* calc tangent plane vectors */
-				v[0] = pos[0] - lampco[0];
-				v[1] = pos[1] - lampco[1];
-				v[2] = pos[2] - lampco[2];
+				v[0] = co[0] - lampco[0];
+				v[1] = co[1] - lampco[1];
+				v[2] = co[2] - lampco[2];
 				Normalize(v);
 				VecOrthoBasisf(v, ru, rv);
 				
@@ -1879,13 +1908,6 @@
 				s[2] = samp3d[0]*ru[2] + samp3d[1]*rv[2];
 				
 				VECCOPY(samp3d, s);
-
-				if(jitbias != 0.0f) {
-					/* bias away somewhat to avoid self intersection */
-					pos[0] -= jitbias*v[0];
-					pos[1] -= jitbias*v[1];
-					pos[2] -= jitbias*v[2];
-				}
 			}
 			else {
 				/* sampling, returns quasi-random vector in [sizex,sizey]^2 plane */
@@ -1901,21 +1923,21 @@
 			VECCOPY(isec->end, vec);
 		}
 
-		if(jitbias != 0.0f && !(do_soft && lar->type==LA_LOCAL)) {
+		if(shi->strand) {
 			/* bias away somewhat to avoid self intersection */
+			float jitbias= 0.5f*(VecLength(shi->dxco) + VecLength(shi->dyco));
 			float v[3];
 
-			VECSUB(v, pos, isec->end);
+			VECSUB(v, co, isec->end);
 			Normalize(v);
 
-			pos[0] -= jitbias*v[0];
-			pos[1] -= jitbias*v[1];
-			pos[2] -= jitbias*v[2];
+			co[0] -= jitbias*v[0];
+			co[1] -= jitbias*v[1];
+			co[2] -= jitbias*v[2];
 		}
 
-		VECCOPY(isec->start, pos);
+		VECCOPY(isec->start, co);
 		
-		
 		/* trace the ray */
 		if(isec->mode==RE_RAY_SHADOW_TRA) {
 			isec->col[0]= isec->col[1]= isec->col[2]=  1.0f;
@@ -1941,7 +1963,7 @@
 		if ((lar->ray_samp_method == LA_SAMP_HALTON)) {
 		
 			/* adaptive sampling - consider samples below threshold as in shadow (or vice versa) and exit early */
-			if ((max_samples > 4) && (adapt_thresh > 0.0) && (samples > max_samples / 3)) {
+			if ((max_samples > min_adapt_samples) && (adapt_thresh > 0.0) && (samples > max_samples / 3)) {
 				if (isec->mode==RE_RAY_SHADOW_TRA) {
 					if ((shadfac[3] / samples > (1.0-adapt_thresh)) || (shadfac[3] / samples < adapt_thresh))
 						break;
@@ -1963,8 +1985,6 @@
 	} else
 		shadfac[3]= 1.0f-fac/samples;
 
-	if (qsa_jit)
-		release_thread_qmcsampler(&R, shi->thread, qsa_jit);
 	if (qsa)
 		release_thread_qmcsampler(&R, shi->thread, qsa);
 }

Modified: trunk/blender/source/blender/render/intern/source/rendercore.c
===================================================================
--- trunk/blender/source/blender/render/intern/source/rendercore.c	2008-10-07 14:24:08 UTC (rev 16959)
+++ trunk/blender/source/blender/render/intern/source/rendercore.c	2008-10-07 15:01:44 UTC (rev 16960)
@@ -1465,7 +1465,7 @@
 {
 	ShadeInput *shi= ssamp->shi;
 	ShadeResult shr;
-	float texfac, orthoarea, nor[3], alpha;
+	float texfac, orthoarea, nor[3], alpha, sx, sy;
 
 	/* cache for shadow */
 	shi->samplenr= R.shadowsamplenr[shi->thread]++;
@@ -1476,8 +1476,8 @@
 		shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);
 
 	/* center pixel */
-	x += 0.5f;
-	y += 0.5f;
+	sx = x + 0.5f;
+	sy = y + 0.5f;
 
 	/* we estimate the area here using shi->dxco and shi->dyco. we need to
 	   enabled shi->osatex these are filled. we compute two areas, one with
@@ -1486,13 +1486,13 @@
 	shi->osatex= 1;
 
 	VECCOPY(nor, shi->facenor);
-	calc_view_vector(shi->facenor, x, y);
+	calc_view_vector(shi->facenor, sx, sy);
 	Normalize(shi->facenor);
-	shade_input_set_viewco(shi, x, y, z);
+	shade_input_set_viewco(shi, x, y, sx, sy, z);
 	orthoarea= VecLength(shi->dxco)*VecLength(shi->dyco);
 
 	VECCOPY(shi->facenor, nor);
-	shade_input_set_viewco(shi, x, y, z);
+	shade_input_set_viewco(shi, x, y, sx, sy, z);
 	*area= VecLength(shi->dxco)*VecLength(shi->dyco);
 	*area= MIN2(*area, 2.0f*orthoarea);
 

Modified: trunk/blender/source/blender/render/intern/source/shadeinput.c
===================================================================
--- trunk/blender/source/blender/render/intern/source/shadeinput.c	2008-10-07 14:24:08 UTC (rev 16959)
+++ trunk/blender/source/blender/render/intern/source/shadeinput.c	2008-10-07 15:01:44 UTC (rev 16960)
@@ -573,31 +573,25 @@
 	}
 }
 
-/* scanline pixel coordinates */
-/* requires set_triangle */
-void shade_input_set_viewco(ShadeInput *shi, float x, float y, float z)
+/* from scanline pixel coordinates to 3d coordinates, requires set_triangle */
+void shade_input_calc_viewco(ShadeInput *shi, float x, float y, float z, float *view, float *dxyview, float *co, float *dxco, float *dyco)
 {
-	float fac;
+	/* returns not normalized, so is in viewplane coords */
+	calc_view_vector(view, x, y);
 	

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list