[Bf-blender-cvs] [676e1cb] master: Cycles code refactor: move some more volume code into separate functions.

Brecht Van Lommel noreply at git.blender.org
Sat Mar 29 15:33:19 CET 2014


Commit: 676e1cbe40cef4bbaffd0346ea467e10e04ed4d1
Author: Brecht Van Lommel
Date:   Sat Mar 29 13:03:49 2014 +0100
https://developer.blender.org/rB676e1cbe40cef4bbaffd0346ea467e10e04ed4d1

Cycles code refactor: move some more volume code into separate functions.

===================================================================

M	intern/cycles/kernel/kernel_volume.h

===================================================================

diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index 19e1629..1282e59 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -193,7 +193,7 @@ ccl_device_noinline void kernel_volume_shadow(KernelGlobals *kg, PathState *stat
 /* Equi-angular sampling as in:
  * "Importance Sampling Techniques for Path Tracing in Participating Media" */
 
-ccl_device float kernel_volume_equiangular_sample(Ray *ray, float3 light_P, float xi, float *pdf)
+ccl_device float kernel_volume_equiangular_sample(Ray *ray, float3 sigma_t, float3 light_P, float xi, float3 *transmittance, float *pdf)
 {
 	float t = ray->t;
 
@@ -205,7 +205,10 @@ ccl_device float kernel_volume_equiangular_sample(Ray *ray, float3 light_P, floa
 
 	*pdf = D / ((theta_b - theta_a) * (D * D + t_ * t_));
 
-	return min(t, delta + t_); /* min is only for float precision errors */
+	float sample_t = min(t, delta + t_); /* min is only for float precision errors */
+	*transmittance = volume_color_attenuation(sigma_t, sample_t);
+
+	return sample_t;
 }
 
 ccl_device float kernel_volume_equiangular_pdf(Ray *ray, float3 light_P, float sample_t)
@@ -224,6 +227,69 @@ ccl_device float kernel_volume_equiangular_pdf(Ray *ray, float3 light_P, float s
 	return pdf;
 }
 
+ccl_device bool kernel_volume_equiangular_light_position(KernelGlobals *kg, PathState *state, Ray *ray, RNG *rng, float3 *light_P)
+{
+	/* light RNGs */
+	float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT);
+	float light_u, light_v;
+	path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
+
+	/* light sample */
+	LightSample ls;
+	light_sample(kg, light_t, light_u, light_v, ray->time, ray->P, &ls);
+	if(ls.pdf == 0.0f)
+		return false;
+	
+	*light_P = ls.P;
+	return true;
+}
+
+/* Distance sampling */
+
+ccl_device bool kernel_volume_distance_sample(Ray *ray, float3 sigma_t, int channel, float xi, float *sample_t, float3 *transmittance, float *pdf)
+{
+	/* xi is [0, 1[ so log(0) should never happen, division by zero is
+	 * avoided because sample_sigma_t > 0 when SD_SCATTER is set */
+	float sample_sigma_t = kernel_volume_channel_get(sigma_t, channel);
+
+	*sample_t = min(ray->t, -logf(1.0f - xi)/sample_sigma_t);
+	*transmittance = volume_color_attenuation(sigma_t, *sample_t);
+
+	if(*sample_t < ray->t) {
+		/* hit */
+		*pdf = dot(sigma_t, *transmittance) * (1.0f/3.0f);
+		return true;
+	}
+	else {
+		/* miss */
+		*pdf = (transmittance->x + transmittance->y + transmittance->z) * (1.0f/3.0f);
+		return false;
+	}
+}
+
+/* Emission */
+
+ccl_device float3 kernel_volume_emission_integrate(VolumeShaderCoefficients *coeff, int closure_flag, float3 transmittance, float t)
+{
+	/* integral E * exp(-sigma_t * t) from 0 to t = E * (1 - exp(-sigma_t * t))/sigma_t
+	 * this goes to E * t as sigma_t goes to zero
+	 *
+	 * todo: we should use an epsilon to avoid precision issues near zero sigma_t */
+	float3 emission = coeff->emission;
+
+	if(closure_flag & SD_ABSORPTION) {
+		float3 sigma_t = coeff->sigma_a + coeff->sigma_s;
+
+		emission.x *= (sigma_t.x > 0.0f)? (1.0f - transmittance.x)/sigma_t.x: t;
+		emission.y *= (sigma_t.y > 0.0f)? (1.0f - transmittance.y)/sigma_t.y: t;
+		emission.z *= (sigma_t.z > 0.0f)? (1.0f - transmittance.z)/sigma_t.z: t;
+	}
+	else
+		emission *= t;
+	
+	return emission;
+}
+
 /* Volume Path */
 
 /* homogeneous volume: assume shader evaluation at the start gives
@@ -257,21 +323,17 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba
 
 		/* distance sampling */
 		if(kernel_data.integrator.volume_homogeneous_sampling == 0 || !kernel_data.integrator.num_all_lights) { 
-			/* xi is [0, 1[ so log(0) should never happen, division by zero is
-			 * avoided because sample_sigma_t > 0 when SD_SCATTER is set */
 			float xi = path_state_rng_1D(kg, rng, state, PRNG_SCATTER_DISTANCE);
-			float sample_t = min(t, -logf(1.0f - xi)/sample_sigma_t);
+			float pdf, sample_t;
 
-			transmittance = volume_color_attenuation(sigma_t, sample_t);
-
-			if(sample_t < t) {
-				float pdf = dot(sigma_t, transmittance);
-				new_tp = *throughput * coeff.sigma_s * transmittance * (3.0f / pdf);
+			if(kernel_volume_distance_sample(ray, sigma_t, channel, xi, &sample_t, &transmittance, &pdf)) {
+				/* hit */
+				new_tp = *throughput * coeff.sigma_s * transmittance / pdf;
 				t = sample_t;
 			}
 			else {
-				float pdf = (transmittance.x + transmittance.y + transmittance.z);
-				new_tp = *throughput * transmittance * (3.0f / pdf);
+				/* miss */
+				new_tp = *throughput * transmittance / pdf;
 			}
 		}
 		/* equi-angular sampling */
@@ -292,22 +354,14 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba
 				/* rescale random number so we can reuse it */
 				xi = (xi - sample_transmittance)/(1.0f - sample_transmittance);
 
-				/* light RNGs */
-				float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT);
-				float light_u, light_v;
-				path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
-
-				/* light sample */
-				LightSample ls;
-				light_sample(kg, light_t, light_u, light_v, ray->time, ray->P, &ls);
-				if(ls.pdf == 0.0f)
+				/* sample position on light */
+				float3 light_P;
+				if(!kernel_volume_equiangular_light_position(kg, state, ray, rng, &light_P))
 					return VOLUME_PATH_MISSED;
 
 				/* sampling */
-				float sample_t, pdf;
-				sample_t = kernel_volume_equiangular_sample(ray, ls.P, xi, &pdf);
-
-				transmittance = volume_color_attenuation(sigma_t, sample_t);
+				float pdf;
+				float sample_t = kernel_volume_equiangular_sample(ray, sigma_t, light_P, xi, &transmittance, &pdf);
 
 				new_tp = *throughput * coeff.sigma_s * transmittance / ((1.0f - sample_transmittance) * pdf);
 				t = sample_t;
@@ -320,24 +374,9 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba
 		new_tp = *throughput * transmittance;
 	}
 
-	/* integrate emission attenuated by extinction
-	 * integral E * exp(-sigma_t * t) from 0 to t = E * (1 - exp(-sigma_t * t))/sigma_t
-	 * this goes to E * t as sigma_t goes to zero
-	 *
-	 * todo: we should use an epsilon to avoid precision issues near zero sigma_t */
+	/* integrate emission attenuated by extinction */
 	if(closure_flag & SD_EMISSION) {
-		float3 emission = coeff.emission;
-
-		if(closure_flag & SD_ABSORPTION) {
-			float3 sigma_t = coeff.sigma_a + coeff.sigma_s;
-
-			emission.x *= (sigma_t.x > 0.0f)? (1.0f - transmittance.x)/sigma_t.x: t;
-			emission.y *= (sigma_t.y > 0.0f)? (1.0f - transmittance.y)/sigma_t.y: t;
-			emission.z *= (sigma_t.z > 0.0f)? (1.0f - transmittance.z)/sigma_t.z: t;
-		}
-		else
-			emission *= t;
-
+		float3 emission = kernel_volume_emission_integrate(&coeff, closure_flag, transmittance, t);
 		path_radiance_accum_emission(L, *throughput, emission, state->bounce);
 	}
 
@@ -468,24 +507,9 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous(KernelGlo
 				 * tp_eps check too */
 			}
 
-			/* integrate emission attenuated by absorption 
-			 * integral E * exp(-sigma_t * t) from 0 to t = E * (1 - exp(-sigma_t * t))/sigma_t
-			 * this goes to E * t as sigma_t goes to zero
-			 *
-			 * todo: we should use an epsilon to avoid precision issues near zero sigma_t */
+			/* integrate emission attenuated by absorption */
 			if(closure_flag & SD_EMISSION) {
-				float3 emission = coeff.emission;
-
-				if(closure_flag & SD_ABSORPTION) {
-					float3 sigma_t = coeff.sigma_a + coeff.sigma_s;
-
-					emission.x *= (sigma_t.x > 0.0f)? (1.0f - transmittance.x)/sigma_t.x: dt;
-					emission.y *= (sigma_t.y > 0.0f)? (1.0f - transmittance.y)/sigma_t.y: dt;
-					emission.z *= (sigma_t.z > 0.0f)? (1.0f - transmittance.z)/sigma_t.z: dt;
-				}
-				else
-					emission *= dt;
-
+				float3 emission = kernel_volume_emission_integrate(&coeff, closure_flag, transmittance, dt);
 				path_radiance_accum_emission(L, tp, emission, state->bounce);
 			}




More information about the Bf-blender-cvs mailing list