Fix #131723: Cycles volume not sampling channels with zero extinction
The original paper uses the single scattering albedo `sigma_s/sigma_t` to pick a channel for sampling the scattering distance. However, this only considers the situation where there is scattering inside the volume. If some channel has an extinction coefficient of zero, the light passes through without attenuation for that channel. We assign such channel with a weight of 1 instead of 0 to make sure it can be sampled. Pull Request: https://projects.blender.org/blender/blender/pulls/131741
This commit is contained in:
committed by
Weizhen Huang
parent
b8d67aa10f
commit
27fc091be8
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user