Cycles: improve adaptive sampling for overexposed scenes

Render time is reduced for overexposed scenes, by taking into account absolute
light intensity for adaptive sampling.

This can negatively affect some scenes where compositing or color management
are used to make the scene much darker or lighter. For best results adjust the
Film > Exposure setting to bring the intensity into a good range, and then do
further compositing and color management on top of that. Note that this setting
is different than color management exposure.

Previously Cycles' adaptive sampling used sqrt(I) to normalize noise level to
conform to a viewer's eye sensitivity. It is great for darker regions of the
image, but also requests too much samples in bright regions, sometimes several
times more than needed. Highlights can tolerate more noise because in most
examples it is still less noticeable then the noise in darker areas in the same
render.

Differential Revision: https://developer.blender.org/D16392
This commit is contained in:
Mikhail Matrosov 2022-11-14 14:13:52 +01:00 committed by Brecht Van Lommel
parent d7f1430f11
commit 857bb1b5ec
Notes: blender-bot 2023-02-14 08:42:53 +01:00
Referenced by issue #74581, Cycles: adaptive sampling improvements
1 changed files with 18 additions and 3 deletions

View File

@ -58,13 +58,28 @@ ccl_device bool film_adaptive_sampling_convergence_check(KernelGlobals kg,
const float4 I = kernel_read_pass_float4(buffer + kernel_data.film.pass_combined);
const float sample = __float_as_uint(buffer[kernel_data.film.pass_sample_count]);
const float inv_sample = 1.0f / sample;
const float intensity_scale = kernel_data.film.exposure / sample;
/* The per pixel error as seen in section 2.1 of
* "A hierarchical automatic stopping condition for Monte Carlo global illumination" */
const float error_difference = (fabsf(I.x - A.x) + fabsf(I.y - A.y) + fabsf(I.z - A.z)) *
inv_sample;
const float error_normalize = sqrtf((I.x + I.y + I.z) * inv_sample);
intensity_scale;
const float intensity = (I.x + I.y + I.z) * intensity_scale;
/* Anything with R+G+B > 1 is highly exposed - even in sRGB it's a range that
* some displays aren't even able to display without significant losses in
* detalization. Everything with R+G+B > 3 is overexposed and should receive
* even less samples. Filmic-like curves need maximum sampling rate at
* intensity near 0.1-0.2, so threshold of 1 for R+G+B leaves an additional
* fstop in case it is needed for compositing.
*/
float error_normalize;
if (intensity < 1.0f) {
error_normalize = sqrtf(intensity);
} else {
error_normalize = intensity;
}
/* A small epsilon is added to the divisor to prevent division by zero. */
const float error = error_difference / (0.0001f + error_normalize);
const bool did_converge = (error < threshold);