Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/kernel/kernel_volume.h97
1 files changed, 68 insertions, 29 deletions
diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index 5604d8e5163..2af4c9a5e7a 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -74,7 +74,8 @@ ccl_device_inline bool volume_shader_sample(KernelGlobals *kg,
make_float3(0.0f, 0.0f, 0.0f);
if(sd->flag & SD_SCATTER) {
- if(state->volume_bounce < kernel_data.integrator.max_volume_bounce) {
+ if(state->bounce < kernel_data.integrator.max_bounce &&
+ state->volume_bounce < kernel_data.integrator.max_volume_bounce) {
for(int i = 0; i < sd->num_closure; i++) {
const ShaderClosure *sc = &sd->closure[i];
@@ -340,6 +341,34 @@ ccl_device float3 kernel_volume_emission_integrate(VolumeShaderCoefficients *coe
/* Volume Path */
+ccl_device int kernel_volume_sample_channel(float3 albedo, float3 throughput, float rand, float3 *pdf)
+{
+ /* Sample color channel proportional to throughput and single scattering
+ * albedo, to significantly reduce noise with many bounce, following:
+ *
+ * "Practical and Controllable Subsurface Scattering for Production Path
+ * Tracing". Matt Jen-Yuan Chiang, Peter Kutz, Brent Burley. SIGGRAPH 2016. */
+ float3 weights = fabs(throughput * albedo);
+ float sum_weights = weights.x + weights.y + weights.z;
+
+ if(sum_weights > 0.0f) {
+ *pdf = weights/sum_weights;
+ }
+ else {
+ *pdf = make_float3(1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f);
+ }
+
+ if(rand < pdf->x) {
+ return 0;
+ }
+ else if(rand < pdf->x + pdf->y) {
+ return 1;
+ }
+ else {
+ return 2;
+ }
+}
+
/* homogeneous volume: assume shader evaluation at the start gives
* the volume shading coefficient for the entire line segment */
ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(
@@ -363,20 +392,18 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(
#ifdef __VOLUME_SCATTER__
/* randomly scatter, and if we do t is shortened */
if(closure_flag & SD_SCATTER) {
- /* extinction coefficient */
- float3 sigma_t = coeff.sigma_t;
-
- /* pick random color channel, we use the Veach one-sample
- * model with balance heuristic for the channels */
+ /* Sample channel, use MIS with balance heuristic. */
float rphase = path_state_rng_1D(kg, state, PRNG_PHASE_CHANNEL);
- int channel = (int)(rphase*3.0f);
+ float3 albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t);
+ float3 channel_pdf;
+ int channel = kernel_volume_sample_channel(albedo, *throughput, rphase, &channel_pdf);
/* decide if we will hit or miss */
bool scatter = true;
float xi = path_state_rng_1D(kg, state, PRNG_SCATTER_DISTANCE);
if(probalistic_scatter) {
- float sample_sigma_t = kernel_volume_channel_get(sigma_t, channel);
+ float sample_sigma_t = kernel_volume_channel_get(coeff.sigma_t, channel);
float sample_transmittance = expf(-sample_sigma_t * t);
if(1.0f - xi >= sample_transmittance) {
@@ -397,19 +424,19 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(
float sample_t;
/* distance sampling */
- sample_t = kernel_volume_distance_sample(ray->t, sigma_t, channel, xi, &transmittance, &pdf);
+ sample_t = kernel_volume_distance_sample(ray->t, coeff.sigma_t, channel, xi, &transmittance, &pdf);
/* modify pdf for hit/miss decision */
if(probalistic_scatter)
- pdf *= make_float3(1.0f, 1.0f, 1.0f) - volume_color_transmittance(sigma_t, t);
+ pdf *= make_float3(1.0f, 1.0f, 1.0f) - volume_color_transmittance(coeff.sigma_t, t);
- new_tp = *throughput * coeff.sigma_s * transmittance / average(pdf);
+ new_tp = *throughput * coeff.sigma_s * transmittance / dot(channel_pdf, pdf);
t = sample_t;
}
else {
/* no scattering */
- float3 transmittance = volume_color_transmittance(sigma_t, t);
- float pdf = average(transmittance);
+ float3 transmittance = volume_color_transmittance(coeff.sigma_t, t);
+ float pdf = dot(channel_pdf, transmittance);
new_tp = *throughput * transmittance / pdf;
}
}
@@ -423,8 +450,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(
/* integrate emission attenuated by extinction */
if(L && (closure_flag & SD_EMISSION)) {
- float3 sigma_t = coeff.sigma_t;
- float3 transmittance = volume_color_transmittance(sigma_t, ray->t);
+ float3 transmittance = volume_color_transmittance(coeff.sigma_t, ray->t);
float3 emission = kernel_volume_emission_integrate(&coeff, closure_flag, transmittance, ray->t);
path_radiance_accum_emission(L, state, *throughput, emission);
}
@@ -473,7 +499,6 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
* model with balance heuristic for the channels */
float xi = path_state_rng_1D(kg, state, PRNG_SCATTER_DISTANCE);
float rphase = path_state_rng_1D(kg, state, PRNG_PHASE_CHANNEL);
- int channel = (int)(rphase*3.0f);
bool has_scatter = false;
for(int i = 0; i < max_steps; i++) {
@@ -500,32 +525,34 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
if((closure_flag & SD_SCATTER) || (has_scatter && (closure_flag & SD_EXTINCTION))) {
has_scatter = true;
- float3 sigma_t = coeff.sigma_t;
- float3 sigma_s = coeff.sigma_s;
+ /* Sample channel, use MIS with balance heuristic. */
+ float3 albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t);
+ float3 channel_pdf;
+ int channel = kernel_volume_sample_channel(albedo, tp, rphase, &channel_pdf);
/* compute transmittance over full step */
- transmittance = volume_color_transmittance(sigma_t, dt);
+ transmittance = volume_color_transmittance(coeff.sigma_t, dt);
/* decide if we will scatter or continue */
float sample_transmittance = kernel_volume_channel_get(transmittance, channel);
if(1.0f - xi >= sample_transmittance) {
/* compute sampling distance */
- float sample_sigma_t = kernel_volume_channel_get(sigma_t, channel);
+ float sample_sigma_t = kernel_volume_channel_get(coeff.sigma_t, channel);
float new_dt = -logf(1.0f - xi)/sample_sigma_t;
new_t = t + new_dt;
/* transmittance and pdf */
- float3 new_transmittance = volume_color_transmittance(sigma_t, new_dt);
- float3 pdf = sigma_t * new_transmittance;
+ float3 new_transmittance = volume_color_transmittance(coeff.sigma_t, new_dt);
+ float3 pdf = coeff.sigma_t * new_transmittance;
/* throughput */
- new_tp = tp * sigma_s * new_transmittance / average(pdf);
+ new_tp = tp * coeff.sigma_s * new_transmittance / dot(channel_pdf, pdf);
scatter = true;
}
else {
/* throughput */
- float pdf = average(transmittance);
+ float pdf = dot(channel_pdf, transmittance);
new_tp = tp * transmittance / pdf;
/* remap xi so we can reuse it and keep thing stratified */
@@ -632,6 +659,7 @@ typedef struct VolumeSegment {
float3 accum_emission; /* accumulated emission at end of segment */
float3 accum_transmittance; /* accumulated transmittance at end of segment */
+ float3 accum_albedo; /* accumulated average albedo over segment */
int sampling_method; /* volume sampling method */
} VolumeSegment;
@@ -698,6 +726,7 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta
/* init accumulation variables */
float3 accum_emission = make_float3(0.0f, 0.0f, 0.0f);
float3 accum_transmittance = make_float3(1.0f, 1.0f, 1.0f);
+ float3 accum_albedo = make_float3(0.0f, 0.0f, 0.0f);
float3 cdf_distance = make_float3(0.0f, 0.0f, 0.0f);
float t = 0.0f;
@@ -724,6 +753,11 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta
int closure_flag = sd->flag;
float3 sigma_t = coeff.sigma_t;
+ /* compute average albedo for channel sampling */
+ if(closure_flag & SD_SCATTER) {
+ accum_albedo += dt * safe_divide_color(coeff.sigma_s, sigma_t);
+ }
+
/* compute accumulated transmittance */
float3 transmittance = volume_color_transmittance(sigma_t, dt);
@@ -783,6 +817,7 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta
/* store total emission and transmittance */
segment->accum_emission = accum_emission;
segment->accum_transmittance = accum_transmittance;
+ segment->accum_albedo = accum_albedo;
/* normalize cumulative density function for distance sampling */
VolumeStep *last_step = segment->steps + segment->numsteps - 1;
@@ -825,9 +860,13 @@ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(
{
kernel_assert(segment->closure_flag & SD_SCATTER);
- /* pick random color channel, we use the Veach one-sample
- * model with balance heuristic for the channels */
- int channel = (int)(rphase*3.0f);
+ /* Sample color channel, use MIS with balance heuristic. */
+ float3 channel_pdf;
+ int channel = kernel_volume_sample_channel(segment->accum_albedo,
+ *throughput,
+ rphase,
+ &channel_pdf);
+
float xi = rscatter;
/* probabilistic scattering decision based on transmittance */
@@ -914,7 +953,7 @@ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(
if(probalistic_scatter)
distance_pdf *= make_float3(1.0f, 1.0f, 1.0f) - segment->accum_transmittance;
- pdf = average(distance_pdf * step_pdf_distance);
+ pdf = dot(channel_pdf, distance_pdf * step_pdf_distance);
/* multiple importance sampling */
if(use_mis) {
@@ -977,7 +1016,7 @@ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(
/* multiple importance sampling */
if(use_mis) {
float3 distance_pdf3 = kernel_volume_distance_pdf(step_t, step->sigma_t, step_sample_t);
- float distance_pdf = average(distance_pdf3 * step_pdf_distance);
+ float distance_pdf = dot(channel_pdf, distance_pdf3 * step_pdf_distance);
mis_weight = 2.0f*power_heuristic(pdf, distance_pdf);
}
}