[Bf-blender-cvs] [28954ce] master: Cycles code refactor: move some volume code to separate functions.

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


Commit: 28954ce9c4cdc7074dd8d585917ead2a925160d9
Author: Brecht Van Lommel
Date:   Sat Mar 29 13:03:48 2014 +0100
https://developer.blender.org/rB28954ce9c4cdc7074dd8d585917ead2a925160d9

Cycles code refactor: move some volume code to 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 e4508f2..31c601a 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -97,6 +97,11 @@ ccl_device float3 volume_color_attenuation(float3 sigma, float t)
 	return make_float3(expf(-sigma.x * t), expf(-sigma.y * t), expf(-sigma.z * t));
 }
 
+ccl_device float kernel_volume_channel_get(float3 value, int channel)
+{
+	return (channel == 0)? value.x: ((channel == 1)? value.y: value.z);
+}
+
 ccl_device bool volume_stack_is_heterogeneous(KernelGlobals *kg, VolumeStack *stack)
 {
 	for(int i = 0; stack[i].shader != SHADER_NONE; i++) {
@@ -190,6 +195,40 @@ ccl_device_noinline void kernel_volume_shadow(KernelGlobals *kg, PathState *stat
 		kernel_volume_shadow_homogeneous(kg, state, ray, &sd, throughput);
 }
 
+/* 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)
+{
+	float t = ray->t;
+
+	float delta = dot((light_P - ray->P) , ray->D);
+	float D = sqrtf(len_squared(light_P - ray->P) - delta * delta);
+	float theta_a = -atan2f(delta, D);
+	float theta_b = atan2f(t - delta, D);
+	float t_ = D * tan((xi * theta_b) + (1 - xi) * theta_a);
+
+	*pdf = D / ((theta_b - theta_a) * (D * D + t_ * t_));
+
+	return min(t, delta + t_); /* min is only for float precision errors */
+}
+
+ccl_device float kernel_volume_equiangular_pdf(Ray *ray, float3 light_P, float sample_t)
+{
+	float delta = dot((light_P - ray->P) , ray->D);
+	float D = sqrtf(len_squared(light_P - ray->P) - delta * delta);
+
+	float t = ray->t;
+	float t_ = sample_t - delta;
+
+	float theta_a = -atan2f(delta, D);
+	float theta_b = atan2f(t - delta, D);
+
+	float pdf = D / ((theta_b - theta_a) * (D * D + t_ * t_));
+
+	return pdf;
+}
+
 /* Volume Path */
 
 /* homogeneous volume: assume shader evaluation at the start gives
@@ -219,14 +258,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba
 
 		/* pick random color channel, we use the Veach one-sample
 		 * model with balance heuristic for the channels */
-		float sample_sigma_t;
-
-		if(channel == 0)
-			sample_sigma_t = sigma_t.x;
-		else if(channel == 1)
-			sample_sigma_t = sigma_t.y;
-		else
-			sample_sigma_t = sigma_t.z;
+		float sample_sigma_t = kernel_volume_channel_get(sigma_t, channel);
 
 		/* distance sampling */
 		if(kernel_data.integrator.volume_homogeneous_sampling == 0 || !kernel_data.integrator.num_all_lights) { 
@@ -265,9 +297,6 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba
 				/* rescale random number so we can reuse it */
 				xi = (xi - sample_transmittance)/(1.0f - sample_transmittance);
 
-				/* equi-angular scattering somewhere on segment 0..t */
-				/* see "Importance Sampling Techniques for Path Tracing in Participating Media" */
-
 				/* light RNGs */
 				float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT);
 				float light_u, light_v;
@@ -280,14 +309,8 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba
 					return VOLUME_PATH_MISSED;
 
 				/* sampling */
-				float delta = dot((ls.P - ray->P) , ray->D);
-				float D = sqrtf(len_squared(ls.P - ray->P) - delta * delta);
-				float theta_a = -atan2f(delta, D);
-				float theta_b = atan2f(t - delta, D);
-				float t_ = D * tan((xi * theta_b) + (1 - xi) * theta_a);
-
-				float pdf = D / ((theta_b - theta_a) * (D * D + t_ * t_));
-				float sample_t = min(t, delta + t_);
+				float sample_t, pdf;
+				sample_t = kernel_volume_equiangular_sample(ray, ls.P, xi, &pdf);
 
 				transmittance = volume_color_attenuation(sigma_t, sample_t);
 
@@ -409,14 +432,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous(KernelGlo
 
 				/* pick random color channel, we use the Veach one-sample
 				 * model with balance heuristic for the channels */
-				float sample_sigma_t;
-
-				if(channel == 0)
-					sample_sigma_t = accum_sigma_t.x + dt*sigma_t.x;
-				else if(channel == 1)
-					sample_sigma_t = accum_sigma_t.y + dt*sigma_t.y;
-				else
-					sample_sigma_t = accum_sigma_t.z + dt*sigma_t.z;
+				float sample_sigma_t = kernel_volume_channel_get(accum_sigma_t + dt*sigma_t, channel);
 
 				if(nlogxi < sample_sigma_t) {
 					/* compute sampling distance */
@@ -540,10 +556,11 @@ ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate(KernelGlobals
 	 * in random number generator later, for now this is done here to not impact
 	 * performance of rendering without volumes */
 	RNG tmp_rng = cmj_hash(*rng, state->rng_offset);
+	bool heterogeneous = volume_stack_is_heterogeneous(kg, state->volume_stack);
 
 	shader_setup_from_volume(kg, sd, ray, state->bounce);
 
-	if(volume_stack_is_heterogeneous(kg, state->volume_stack))
+	if(heterogeneous)
 		return kernel_volume_integrate_heterogeneous(kg, state, ray, sd, L, throughput, &tmp_rng);
 	else
 		return kernel_volume_integrate_homogeneous(kg, state, ray, sd, L, throughput, &tmp_rng);




More information about the Bf-blender-cvs mailing list