[Bf-blender-cvs] [9a77872] master: Cycles code refactor: shuffle homogeneous volume code to factor out hit/miss decision.
Brecht Van Lommel
noreply at git.blender.org
Sat Mar 29 15:33:20 CET 2014
Commit: 9a77872b2b0b6e5a1d0d8987793c4f569eb4a239
Author: Brecht Van Lommel
Date: Sat Mar 29 13:03:49 2014 +0100
https://developer.blender.org/rB9a77872b2b0b6e5a1d0d8987793c4f569eb4a239
Cycles code refactor: shuffle homogeneous volume code to factor out hit/miss decision.
This removes a few optimizations to avoid exp() calls and division, they will be
added back later, at the moment it's more important to make the code easier to
understand and refactor.
===================================================================
M intern/cycles/kernel/kernel_volume.h
===================================================================
diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index 1282e59..f2a02e1 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -92,7 +92,7 @@ ccl_device bool volume_shader_sample(KernelGlobals *kg, ShaderData *sd, PathStat
return true;
}
-ccl_device float3 volume_color_attenuation(float3 sigma, float t)
+ccl_device float3 volume_color_transmittance(float3 sigma, float t)
{
return make_float3(expf(-sigma.x * t), expf(-sigma.y * t), expf(-sigma.z * t));
}
@@ -126,7 +126,7 @@ ccl_device void kernel_volume_shadow_homogeneous(KernelGlobals *kg, PathState *s
float3 sigma_t;
if(volume_shader_extinction_sample(kg, sd, state, ray->P, &sigma_t))
- *throughput *= volume_color_attenuation(sigma_t, ray->t);
+ *throughput *= volume_color_transmittance(sigma_t, ray->t);
}
/* heterogeneous volume: integrate stepping through the volume until we
@@ -161,7 +161,7 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg, PathState
/* todo: we could avoid computing expf() for each step by summing,
* because exp(a)*exp(b) = exp(a+b), but we still want a quick
* tp_eps check too */
- tp *= volume_color_attenuation(sigma_t, new_t - t);
+ tp *= volume_color_transmittance(sigma_t, new_t - t);
/* stop if nearly all light blocked */
if(tp.x < tp_eps && tp.y < tp_eps && tp.z < tp_eps)
@@ -206,7 +206,7 @@ ccl_device float kernel_volume_equiangular_sample(Ray *ray, float3 sigma_t, floa
*pdf = D / ((theta_b - theta_a) * (D * D + t_ * t_));
float sample_t = min(t, delta + t_); /* min is only for float precision errors */
- *transmittance = volume_color_attenuation(sigma_t, sample_t);
+ *transmittance = volume_color_transmittance(sigma_t, sample_t);
return sample_t;
}
@@ -246,25 +246,24 @@ ccl_device bool kernel_volume_equiangular_light_position(KernelGlobals *kg, Path
/* 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)
+ccl_device float kernel_volume_distance_sample(Ray *ray, float3 sigma_t, int channel, float xi, float3 *transmittance, float3 *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);
+ float3 full_transmittance = volume_color_transmittance(sigma_t, ray->t);
+ float sample_transmittance = kernel_volume_channel_get(full_transmittance, channel);
- *sample_t = min(ray->t, -logf(1.0f - xi)/sample_sigma_t);
- *transmittance = volume_color_attenuation(sigma_t, *sample_t);
+ float sample_t = min(ray->t, -logf(1.0f - xi*(1.0f - sample_transmittance))/sample_sigma_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;
- }
+ *transmittance = volume_color_transmittance(sigma_t, sample_t);
+ *pdf = (sigma_t * *transmittance)/(make_float3(1.0f, 1.0f, 1.0f) - full_transmittance);
+
+ /* todo: optimization: when taken together with hit/miss decision,
+ * the full_transmittance cancels out drops out and xi does not
+ * need to be remapped */
+
+ return sample_t;
}
/* Emission */
@@ -310,67 +309,59 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba
/* randomly scatter, and if we do t is shortened */
if(closure_flag & SD_SCATTER) {
+ /* extinction coefficient */
float3 sigma_t = coeff.sigma_a + coeff.sigma_s;
- /* set up variables for sampling */
+ /* pick random color channel, we use the Veach one-sample
+ * model with balance heuristic for the channels */
float rphase = path_state_rng_1D(kg, rng, state, PRNG_PHASE);
int channel = (int)(rphase*3.0f);
sd->randb_closure = rphase*3.0f - channel;
- /* pick random color channel, we use the Veach one-sample
- * model with balance heuristic for the channels */
+ /* decide if we will hit or miss */
+ float xi = path_state_rng_1D(kg, rng, state, PRNG_SCATTER_DISTANCE);
float sample_sigma_t = kernel_volume_channel_get(sigma_t, channel);
+ float sample_transmittance = expf(-sample_sigma_t * t);
- /* distance sampling */
- if(kernel_data.integrator.volume_homogeneous_sampling == 0 || !kernel_data.integrator.num_all_lights) {
- float xi = path_state_rng_1D(kg, rng, state, PRNG_SCATTER_DISTANCE);
- float pdf, sample_t;
+ if(xi >= sample_transmittance) {
+ /* scattering */
+ float3 pdf;
+ float sample_t;
- 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 {
- /* miss */
- new_tp = *throughput * transmittance / pdf;
- }
- }
- /* equi-angular sampling */
- else {
- /* decide if we are going to scatter or not, based on sigma_t. this
- * is not ideal, instead we should perhaps split the path here and
- * do both, and at least add multiple importance sampling */
- float xi = path_state_rng_1D(kg, rng, state, PRNG_SCATTER_DISTANCE);
- float sample_transmittance = expf(-sample_sigma_t * t);
-
- if(xi < sample_transmittance) {
- /* no scattering */
- transmittance = volume_color_attenuation(sigma_t, t);
- float pdf = (transmittance.x + transmittance.y + transmittance.z);
- new_tp = *throughput * transmittance * (3.0f / pdf);
+ /* rescale random number so we can reuse it */
+ xi = (xi - sample_transmittance)/(1.0f - sample_transmittance);
+
+ if(kernel_data.integrator.volume_homogeneous_sampling == 0 || !kernel_data.integrator.num_all_lights) {
+ /* distance sampling */
+ sample_t = kernel_volume_distance_sample(ray, sigma_t, channel, xi, &transmittance, &pdf);
}
else {
- /* rescale random number so we can reuse it */
- xi = (xi - sample_transmittance)/(1.0f - sample_transmittance);
-
- /* sample position on light */
+ /* equiangular sampling */
float3 light_P;
+ float equi_pdf;
if(!kernel_volume_equiangular_light_position(kg, state, ray, rng, &light_P))
return VOLUME_PATH_MISSED;
- /* sampling */
- 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;
+ sample_t = kernel_volume_equiangular_sample(ray, sigma_t, light_P, xi, &transmittance, &equi_pdf);
+ pdf = make_float3(equi_pdf, equi_pdf, equi_pdf);
}
+
+ /* modifiy pdf for hit/miss decision */
+ pdf *= make_float3(1.0f, 1.0f, 1.0f) - volume_color_transmittance(sigma_t, t);
+
+ new_tp = *throughput * coeff.sigma_s * transmittance / ((pdf.x + pdf.y + pdf.z) * (1.0f/3.0f));
+ t = sample_t;
+ }
+ else {
+ /* no scattering */
+ transmittance = volume_color_transmittance(sigma_t, t);
+ float pdf = (transmittance.x + transmittance.y + transmittance.z) * (1.0f/3.0f);
+ new_tp = *throughput * transmittance / pdf;
}
}
else if(closure_flag & SD_ABSORPTION) {
/* absorption only, no sampling needed */
- transmittance = volume_color_attenuation(coeff.sigma_a, t);
+ transmittance = volume_color_transmittance(coeff.sigma_a, t);
new_tp = *throughput * transmittance;
}
@@ -469,7 +460,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous(KernelGlo
new_t = nlogxi/sample_sigma_t;
dt = new_t - t;
- transmittance = volume_color_attenuation(sigma_t, dt);
+ transmittance = volume_color_transmittance(sigma_t, dt);
accum_transmittance *= transmittance;
accum_sigma_t = (accum_sigma_t + dt*sigma_t)/new_t;
@@ -483,7 +474,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous(KernelGlo
scatter = true;
}
else {
- transmittance = volume_color_attenuation(sigma_t, dt);
+ transmittance = volume_color_transmittance(sigma_t, dt);
accum_transmittance *= transmittance;
accum_sigma_t += dt*sigma_t;
@@ -495,7 +486,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous(KernelGlo
else if(closure_flag & SD_ABSORPTION) {
/* absorption only, no sampling needed */
float3 sigma_a = coeff.sigma_a;
- transmittance = volume_color_attenuation(sigma_a, dt);
+ transmittance = volume_color_transmittance(sigma_a, dt);
accum_transmittance *= transmittance;
accum_sigma_t += dt*sigma_a;
More information about the Bf-blender-cvs
mailing list