[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [55760] trunk/blender/intern/cycles/kernel : Fix #34852: multilayer SSS material rendering different in progressive and

Brecht Van Lommel brechtvanlommel at pandora.be
Wed Apr 3 18:12:13 CEST 2013


Revision: 55760
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=55760
Author:   blendix
Date:     2013-04-03 16:12:13 +0000 (Wed, 03 Apr 2013)
Log Message:
-----------
Fix #34852: multilayer SSS material rendering different in progressive and
non-progressive integrator.

Modified Paths:
--------------
    trunk/blender/intern/cycles/kernel/kernel_path.h
    trunk/blender/intern/cycles/kernel/kernel_subsurface.h

Modified: trunk/blender/intern/cycles/kernel/kernel_path.h
===================================================================
--- trunk/blender/intern/cycles/kernel/kernel_path.h	2013-04-03 15:59:54 UTC (rev 55759)
+++ trunk/blender/intern/cycles/kernel/kernel_path.h	2013-04-03 16:12:13 UTC (rev 55760)
@@ -363,7 +363,7 @@
 			/* do bssrdf scatter step if we picked a bssrdf closure */
 			if(sc) {
 				uint lcg_state = lcg_init(rbsdf);
-				subsurface_scatter_step(kg, &sd, state.flag, sc, &lcg_state);
+				subsurface_scatter_step(kg, &sd, state.flag, sc, &lcg_state, false);
 			}
 		}
 #endif
@@ -587,7 +587,7 @@
 			/* do bssrdf scatter step if we picked a bssrdf closure */
 			if(sc) {
 				uint lcg_state = lcg_init(rbsdf);
-				subsurface_scatter_step(kg, &sd, state.flag, sc, &lcg_state);
+				subsurface_scatter_step(kg, &sd, state.flag, sc, &lcg_state, false);
 			}
 		}
 #endif
@@ -996,7 +996,7 @@
 				 * replace the BSSRDF with a diffuse BSDF closure */
 				for(int j = 0; j < num_samples; j++) {
 					ShaderData bssrdf_sd = sd;
-					subsurface_scatter_step(kg, &bssrdf_sd, state.flag, sc, &lcg_state);
+					subsurface_scatter_step(kg, &bssrdf_sd, state.flag, sc, &lcg_state, true);
 
 					/* compute lighting with the BSDF closure */
 					kernel_path_non_progressive_lighting(kg, rng, sample*num_samples + j,

Modified: trunk/blender/intern/cycles/kernel/kernel_subsurface.h
===================================================================
--- trunk/blender/intern/cycles/kernel/kernel_subsurface.h	2013-04-03 15:59:54 UTC (rev 55759)
+++ trunk/blender/intern/cycles/kernel/kernel_subsurface.h	2013-04-03 16:12:13 UTC (rev 55760)
@@ -63,69 +63,85 @@
 			bssrdf_sum += sc->sample_weight;
 	}
 
-	/* pick a random bsdf or bssrdf */
+	/* use bsdf or bssrdf? */
 	float r = sd->randb_closure*(bsdf_sum + bssrdf_sum);
+
+	if(r < bsdf_sum) {
+		/* use bsdf, and adjust randb so we can reuse it for picking a bsdf */
+		sd->randb_closure = r/bsdf_sum;
+		*probability = (bsdf_sum > 0.0f)? (bsdf_sum + bssrdf_sum)/bsdf_sum: 1.0f;
+		return NULL;
+	}
+
+	/* use bssrdf */
+	r -= bsdf_sum;
+	sd->randb_closure = 0.0f; /* not needed anymore */
+
 	float sum = 0.0f;
 
-	int sampled;
-
-	for(sampled = 0; sampled < sd->num_closure; sampled++) {
-		ShaderClosure *sc = &sd->closure[sampled];
+	for(int i = 0; i < sd->num_closure; i++) {
+		ShaderClosure *sc = &sd->closure[i];
 		
-		if(CLOSURE_IS_BSDF(sc->type) || CLOSURE_IS_BSSRDF(sc->type)) {
+		if(CLOSURE_IS_BSSRDF(sc->type)) {
 			sum += sc->sample_weight;
 
 			if(r <= sum) {
-				/* if we picked a bssrdf, return the closure. also return probability
-				 * to adjust throughput depending if we picked a bsdf or bssrdf */
-				if(CLOSURE_IS_BSSRDF(sc->type)) {
-					sd->randb_closure = 0.0f; /* not needed anymore */
 #ifdef BSSRDF_MULTI_EVAL
-					*probability = (bssrdf_sum > 0.0f)? (bsdf_sum + bssrdf_sum)/bssrdf_sum: 1.0f;
+				*probability = (bssrdf_sum > 0.0f)? (bsdf_sum + bssrdf_sum)/bssrdf_sum: 1.0f;
 #else
-					*probability = (bssrdf_sum > 0.0f)? (bsdf_sum + bssrdf_sum)/sc->sample_weight: 1.0f;
+				*probability = (bssrdf_sum > 0.0f)? (bsdf_sum + bssrdf_sum)/sc->sample_weight: 1.0f;
 #endif
-					return sc;
-				}
-				else {
-					/* reuse randb for picking a bsdf */
-					sd->randb_closure = (sd->randb_closure - sum - sc->sample_weight)/sc->sample_weight;
-					*probability = (bsdf_sum > 0.0f)? (bsdf_sum + bssrdf_sum)/bsdf_sum: 1.0f;
-					return NULL;
-				}
+				return sc;
 			}
 		}
 	}
 
+	/* should never happen */
 	*probability = 1.0f;
 	return NULL;
 }
 
 #ifdef BSSRDF_MULTI_EVAL
-__device float3 subsurface_scatter_multi_eval(KernelGlobals *kg, ShaderData *sd, bool hit, float refl, float *r, int num_r)
+__device float3 subsurface_scatter_multi_eval(KernelGlobals *kg, ShaderData *sd, bool hit, float refl, float *r, int num_r, bool all)
 {
 	/* compute pdf */
 	float3 eval_sum = make_float3(0.0f, 0.0f, 0.0f);
 	float pdf_sum = 0.0f;
 	float sample_weight_sum = 0.0f;
+	int num_bssrdf = 0;
 
 	for(int i = 0; i < sd->num_closure; i++) {
 		ShaderClosure *sc = &sd->closure[i];
 		
 		if(CLOSURE_IS_BSSRDF(sc->type)) {
+			float sample_weight = (all)? 1.0f: sc->sample_weight;
+
+			/* compute pdf */
 			float pdf = 1.0f;
 			for(int i = 0; i < num_r; i++)
 				pdf *= bssrdf_pdf(kg, sc->data0, refl, r[i]);
-			//float pdf = bssrdf_pdf(kg, sc->data0, refl, r[num_r-1]);
 
 			eval_sum += sc->weight*pdf;
-			pdf_sum += sc->sample_weight*pdf;
+			pdf_sum += sample_weight*pdf;
 
-			sample_weight_sum += sc->sample_weight;
+			sample_weight_sum += sample_weight;
+			num_bssrdf++;
 		}
 	}
 
-	float inv_pdf_sum = (pdf_sum > 0.0f)? sample_weight_sum/pdf_sum: 0.0f;
+	float inv_pdf_sum;
+	
+	if(pdf_sum > 0.0f) {
+		/* in case of non-progressive integrate we sample all bssrdf's once,
+		 * for progressive we pick one, so adjust pdf for that */
+		if(all)
+			inv_pdf_sum = 1.0f/pdf_sum;
+		else
+			inv_pdf_sum = sample_weight_sum/pdf_sum;
+	}
+	else
+		inv_pdf_sum = 0.0f;
+
 	float3 weight = eval_sum * inv_pdf_sum;
 
 	return weight;
@@ -152,7 +168,7 @@
 }
 
 /* subsurface scattering step, from a point on the surface to another nearby point on the same object */
-__device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, int state_flag, ShaderClosure *sc, uint *lcg_state)
+__device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, int state_flag, ShaderClosure *sc, uint *lcg_state, bool all)
 {
 	float radius = sc->data0;
 	float refl = max(average(sc->weight)*3.0f, 0.0f);
@@ -207,7 +223,7 @@
 
 	/* evaluate subsurface scattering closures */
 #ifdef BSSRDF_MULTI_EVAL
-	weight *= subsurface_scatter_multi_eval(kg, sd, hit, refl, r_attempts, num_attempts);
+	weight *= subsurface_scatter_multi_eval(kg, sd, hit, refl, r_attempts, num_attempts, all);
 #else
 	weight *= sc->weight;
 #endif




More information about the Bf-blender-cvs mailing list