[Bf-blender-cvs] [4882c742b56] cycles-x: Cycles X: tweak adaptive sampling threshold

Brecht Van Lommel noreply at git.blender.org
Mon Sep 6 14:25:37 CEST 2021


Commit: 4882c742b560916264f8622651855b5c8e8d1a5c
Author: Brecht Van Lommel
Date:   Tue Aug 31 14:35:11 2021 +0200
Branches: cycles-x
https://developer.blender.org/rB4882c742b560916264f8622651855b5c8e8d1a5c

Cycles X: tweak adaptive sampling threshold

* Fix incorrect handling of samples in adaptive sampling threshold. The previous
  formula relied on number of samples cancelling out, but this was not the case.
* Base automatic min samples on the adaptive threshold instead of number of samples,
  since we now consider that the main setting to tweak.

Note this changes noise levels in existing renders and requires thresholds to be
tweaked again.

I could not find a significant upside or downsides in scenes when comparing equal
render times. Mainly what this seems to do is make different scenes behave more
consistently with the same noise threshold.

Differential Revision: https://developer.blender.org/D12395

===================================================================

M	intern/cycles/blender/addon/properties.py
M	intern/cycles/kernel/kernel_adaptive_sampling.h
M	intern/cycles/render/integrator.cpp

===================================================================

diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index cbc741c20c3..9d9182a66cc 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -365,7 +365,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
     )
     adaptive_min_samples: IntProperty(
         name="Adaptive Min Samples",
-        description="Minimum AA samples for adaptive sampling, to discover noisy features before stopping sampling. Zero for automatic setting based on number of AA samples",
+        description="Minimum AA samples for adaptive sampling, to discover noisy features before stopping sampling. Zero for automatic setting based on noise threshold",
         min=0, max=4096,
         default=0,
     )
@@ -385,7 +385,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
     )
     preview_adaptive_min_samples: IntProperty(
         name="Adaptive Min Samples",
-        description="Minimum AA samples for adaptive sampling, to discover noisy features before stopping sampling. Zero for automatic setting based on number of AA samples, for viewport renders",
+        description="Minimum AA samples for adaptive sampling, to discover noisy features before stopping sampling. Zero for automatic setting based on noise threshold, for viewport renders",
         min=0, max=4096,
         default=0,
     )
diff --git a/intern/cycles/kernel/kernel_adaptive_sampling.h b/intern/cycles/kernel/kernel_adaptive_sampling.h
index 993cfea951e..2bee12f0473 100644
--- a/intern/cycles/kernel/kernel_adaptive_sampling.h
+++ b/intern/cycles/kernel/kernel_adaptive_sampling.h
@@ -70,13 +70,16 @@ ccl_device bool kernel_adaptive_sampling_convergence_check(const KernelGlobals *
   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;
 
   /* The per pixel error as seen in section 2.1 of
-   * "A hierarchical automatic stopping condition for Monte Carlo global illumination"
-   * A small epsilon is added to the divisor to prevent division by zero. */
-  const float error = (fabsf(I.x - A.x) + fabsf(I.y - A.y) + fabsf(I.z - A.z)) /
-                      (sample * 0.0001f + sqrtf(I.x + I.y + I.z));
-  const bool did_converge = (error < threshold * sample);
+   * "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);
+  /* 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);
 
   const uint aux_w_offset = kernel_data.film.pass_adaptive_aux_buffer + 3;
   buffer[aux_w_offset] = did_converge;
diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp
index e2528eeff1c..7263609339d 100644
--- a/intern/cycles/render/integrator.cpp
+++ b/intern/cycles/render/integrator.cpp
@@ -284,8 +284,18 @@ AdaptiveSampling Integrator::get_adaptive_sampling() const
     return adaptive_sampling;
   }
 
-  if (aa_samples > 0 && adaptive_min_samples == 0) {
-    adaptive_sampling.min_samples = max(4, (int)sqrtf(aa_samples));
+  if (aa_samples > 0 && adaptive_threshold == 0.0f) {
+    adaptive_sampling.threshold = max(0.001f, 1.0f / (float)aa_samples);
+    VLOG(1) << "Cycles adaptive sampling: automatic threshold = " << adaptive_sampling.threshold;
+  }
+  else {
+    adaptive_sampling.threshold = adaptive_threshold;
+  }
+
+  if (adaptive_threshold > 0 && adaptive_min_samples == 0) {
+    /* Threshold 0.1 -> 32, 0.01 -> 64, 0.001 -> 128. */
+    const int min_samples = (int)ceilf(16.0f / sqrtf(adaptive_threshold * 0.3f));
+    adaptive_sampling.min_samples = max(4, min_samples);
     VLOG(1) << "Cycles adaptive sampling: automatic min samples = "
             << adaptive_sampling.min_samples;
   }
@@ -293,19 +303,15 @@ AdaptiveSampling Integrator::get_adaptive_sampling() const
     adaptive_sampling.min_samples = max(4, adaptive_min_samples);
   }
 
+  /* Arbitrary factor that makes the threshold more similar to what is was before,
+   * and gives arguably more intuitive values. */
+  adaptive_sampling.threshold *= 5.0f;
+
   adaptive_sampling.adaptive_step = 16;
 
   DCHECK(is_power_of_two(adaptive_sampling.adaptive_step))
       << "Adaptive step must be a power of two for bitwise operations to work";
 
-  if (aa_samples > 0 && adaptive_threshold == 0.0f) {
-    adaptive_sampling.threshold = max(0.001f, 1.0f / (float)aa_samples);
-    VLOG(1) << "Cycles adaptive sampling: automatic threshold = " << adaptive_sampling.threshold;
-  }
-  else {
-    adaptive_sampling.threshold = adaptive_threshold;
-  }
-
   return adaptive_sampling;
 }



More information about the Bf-blender-cvs mailing list