diff --git a/intern/cycles/kernel/integrator/shade_volume.h b/intern/cycles/kernel/integrator/shade_volume.h index 8b6c554034b..958f73046b8 100644 --- a/intern/cycles/kernel/integrator/shade_volume.h +++ b/intern/cycles/kernel/integrator/shade_volume.h @@ -486,9 +486,12 @@ ccl_device_forceinline void volume_integrate_step_scattering( ccl_private VolumeIntegrateState &ccl_restrict vstate, ccl_private VolumeIntegrateResult &ccl_restrict result) { - /* Pick random color channel, we use the Veach one-sample - * model with balance heuristic for the channels. */ - const Spectrum albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t); + /* Pick random color channel for sampling the scatter distance. We use the Veach one-sample model + * with balance heuristic for the channels. + * Set `albedo` to 1 for the channel where extinction coefficient `sigma_t` is zero, to make sure + * that we sample a distance outside the current segment when that channel is picked, meaning + * light passes through without attenuation. */ + const Spectrum albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t, 1.0f); Spectrum channel_pdf; const int channel = volume_sample_channel( albedo, result.indirect_throughput, &vstate.rchannel, &channel_pdf); diff --git a/intern/cycles/util/math.h b/intern/cycles/util/math.h index cc7cf0fd619..68c74c1c610 100644 --- a/intern/cycles/util/math.h +++ b/intern/cycles/util/math.h @@ -634,12 +634,13 @@ ccl_device_inline Spectrum safe_invert_color(Spectrum a) return a; } -ccl_device_inline Spectrum safe_divide_color(Spectrum a, Spectrum b) +/* Returns `a/b`, and replace the channel value with `fallback` if `b == 0`. */ +ccl_device_inline Spectrum safe_divide_color(Spectrum a, Spectrum b, const float fallback = 0.0f) { FOREACH_SPECTRUM_CHANNEL (i) { GET_SPECTRUM_CHANNEL(a, i) = (GET_SPECTRUM_CHANNEL(b, i) != 0.0f) ? GET_SPECTRUM_CHANNEL(a, i) / GET_SPECTRUM_CHANNEL(b, i) : - 0.0f; + fallback; } return a;