[Bf-blender-cvs] [82cf25dfbfa] master: Cycles: Scrambling distance for the PMJ sampler

William Leeson noreply at git.blender.org
Wed Oct 27 14:24:09 CEST 2021


Commit: 82cf25dfbfad39a64b620c20bbd0d65915827a44
Author: William Leeson
Date:   Wed Oct 27 14:14:43 2021 +0200
Branches: master
https://developer.blender.org/rB82cf25dfbfad39a64b620c20bbd0d65915827a44

Cycles: Scrambling distance for the PMJ sampler

Adds scrambling distance to the PMJ sampler. This is based
on the work by Mathieu Menuet in D12318 who created the original
implementation for the Sobol sampler.

Reviewed By: brecht

Maniphest Tasks: T92181

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

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

M	intern/cycles/blender/addon/ui.py
M	intern/cycles/blender/sync.cpp
M	intern/cycles/integrator/tile.cpp
M	intern/cycles/kernel/sample/jitter.h

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

diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 47907481b03..dfaae666785 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -290,11 +290,11 @@ class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
         col.active = not(cscene.use_adaptive_sampling)
         col.prop(cscene, "sampling_pattern", text="Pattern")
         col = layout.column(align=True)
-        col.active = cscene.sampling_pattern == 'SOBOL' and not cscene.use_adaptive_sampling
+        col.active = not cscene.use_adaptive_sampling
         col.prop(cscene, "scrambling_distance", text="Scrambling Distance Strength")
         col.prop(cscene, "adaptive_scrambling_distance", text="Adaptive Scrambling Distance")
         col = layout.column(align=True)
-        col.active = ((cscene.scrambling_distance < 1.0) or cscene.adaptive_scrambling_distance) and cscene.sampling_pattern == 'SOBOL' and not cscene.use_adaptive_sampling
+        col.active = ((cscene.scrambling_distance < 1.0) or cscene.adaptive_scrambling_distance) and not cscene.use_adaptive_sampling
         col.prop(cscene, "preview_scrambling_distance", text="Viewport Scrambling Distance")
 
         layout.separator()
diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp
index f6f490077a7..e0a13625962 100644
--- a/intern/cycles/blender/sync.cpp
+++ b/intern/cycles/blender/sync.cpp
@@ -340,14 +340,16 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background)
       cscene, "sampling_pattern", SAMPLING_NUM_PATTERNS, SAMPLING_PATTERN_SOBOL);
   integrator->set_sampling_pattern(sampling_pattern);
 
+  bool use_adaptive_sampling = false;
   if (preview) {
-    integrator->set_use_adaptive_sampling(
-        RNA_boolean_get(&cscene, "use_preview_adaptive_sampling"));
+    use_adaptive_sampling = RNA_boolean_get(&cscene, "use_preview_adaptive_sampling");
+    integrator->set_use_adaptive_sampling(use_adaptive_sampling);
     integrator->set_adaptive_threshold(get_float(cscene, "preview_adaptive_threshold"));
     integrator->set_adaptive_min_samples(get_int(cscene, "preview_adaptive_min_samples"));
   }
   else {
-    integrator->set_use_adaptive_sampling(RNA_boolean_get(&cscene, "use_adaptive_sampling"));
+    use_adaptive_sampling = RNA_boolean_get(&cscene, "use_adaptive_sampling");
+    integrator->set_use_adaptive_sampling(use_adaptive_sampling);
     integrator->set_adaptive_threshold(get_float(cscene, "adaptive_threshold"));
     integrator->set_adaptive_min_samples(get_int(cscene, "adaptive_min_samples"));
   }
@@ -361,7 +363,7 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background)
 
   /* only use scrambling distance in the viewport if user wants to and disable with AS */
   bool preview_scrambling_distance = get_boolean(cscene, "preview_scrambling_distance");
-  if ((preview && !preview_scrambling_distance) || sampling_pattern != SAMPLING_PATTERN_SOBOL)
+  if ((preview && !preview_scrambling_distance) || use_adaptive_sampling)
     scrambling_distance = 1.0f;
 
   VLOG(1) << "Used Scrambling Distance: " << scrambling_distance;
diff --git a/intern/cycles/integrator/tile.cpp b/intern/cycles/integrator/tile.cpp
index b49e1b27b83..4a1558cce09 100644
--- a/intern/cycles/integrator/tile.cpp
+++ b/intern/cycles/integrator/tile.cpp
@@ -74,39 +74,9 @@ TileSize tile_calculate_best_size(const int2 &image_size,
   TileSize tile_size;
   const int num_path_states_per_sample = max_num_path_states / num_samples;
   if (scrambling_distance < 0.9f) {
-    /* Prefer large tiles for scrambling distance. */
-    if (image_size.x * image_size.y <= num_path_states_per_sample) {
-      tile_size.width = image_size.x;
-      tile_size.height = image_size.y;
-    }
-    else {
-      /* Pick the option with the biggest tile size */
-      int heightOption = num_path_states_per_sample / image_size.x;
-      int widthOption = num_path_states_per_sample / image_size.y;
-      // Check if these options are possible
-      if ((heightOption > 0) || (widthOption > 0)) {
-        int area1 = image_size.x * heightOption;
-        int area2 = widthOption * image_size.y;
-        /* The option with the biggest pixel area */
-        if (area1 >= area2) {
-          tile_size.width = image_size.x;
-          tile_size.height = heightOption;
-        }
-        else {
-          tile_size.width = widthOption;
-          tile_size.height = image_size.y;
-        }
-      }
-      else {  // Large tiles are not an option so use square tiles
-        if (num_path_states_per_sample != 0) {
-          tile_size.width = round_down_to_power_of_two(lround(sqrt(num_path_states_per_sample)));
-          tile_size.height = tile_size.width;
-        }
-        else {
-          tile_size.width = tile_size.height = 1;
-        }
-      }
-    }
+    /* Prefer large tiles for scrambling distance, bounded by max num path states. */
+    tile_size.width = min(image_size.x, max_num_path_states);
+    tile_size.height = min(image_size.y, max(max_num_path_states / tile_size.width, 1));
   }
   else {
     /* Calculate tile size as if it is the most possible one to fit an entire range of samples.
diff --git a/intern/cycles/kernel/sample/jitter.h b/intern/cycles/kernel/sample/jitter.h
index b62ec7fda42..b76b9b8f23e 100644
--- a/intern/cycles/kernel/sample/jitter.h
+++ b/intern/cycles/kernel/sample/jitter.h
@@ -72,13 +72,27 @@ ccl_device_inline float cmj_randfloat_simple(uint i, uint p)
   return cmj_hash_simple(i, p) * (1.0f / (float)0xFFFFFFFF);
 }
 
+ccl_device_inline float cmj_randfloat_simple_dist(uint i, uint p, float d)
+{
+  return cmj_hash_simple(i, p) * (d / (float)0xFFFFFFFF);
+}
+
 ccl_device float pmj_sample_1D(KernelGlobals kg, uint sample, uint rng_hash, uint dimension)
 {
+  uint hash = rng_hash;
+  float jitter_x = 0.0f;
+  if (kernel_data.integrator.scrambling_distance < 1.0f) {
+    hash = kernel_data.integrator.seed;
+
+    jitter_x = cmj_randfloat_simple_dist(
+        dimension, rng_hash, kernel_data.integrator.scrambling_distance);
+  }
+
   /* Perform Owen shuffle of the sample number to reorder the samples. */
 #ifdef _SIMPLE_HASH_
-  const uint rv = cmj_hash_simple(dimension, rng_hash);
+  const uint rv = cmj_hash_simple(dimension, hash);
 #else /* Use a _REGULAR_HASH_. */
-  const uint rv = cmj_hash(dimension, rng_hash);
+  const uint rv = cmj_hash(dimension, hash);
 #endif
 #ifdef _XOR_SHUFFLE_
 #  warning "Using XOR shuffle."
@@ -101,12 +115,12 @@ ccl_device float pmj_sample_1D(KernelGlobals kg, uint sample, uint rng_hash, uin
 #ifndef _NO_CRANLEY_PATTERSON_ROTATION_
   /* Use Cranley-Patterson rotation to displace the sample pattern. */
 #  ifdef _SIMPLE_HASH_
-  float dx = cmj_randfloat_simple(d, rng_hash);
+  float dx = cmj_randfloat_simple(d, hash);
 #  else
-  float dx = cmj_randfloat(d, rng_hash);
+  float dx = cmj_randfloat(d, hash);
 #  endif
   /* Jitter sample locations and map back into [0 1]. */
-  fx = fx + dx;
+  fx = fx + dx + jitter_x;
   fx = fx - floorf(fx);
 #else
 #  warning "Not using Cranley-Patterson Rotation."
@@ -122,11 +136,23 @@ ccl_device void pmj_sample_2D(KernelGlobals kg,
                               ccl_private float *x,
                               ccl_private float *y)
 {
+  uint hash = rng_hash;
+  float jitter_x = 0.0f;
+  float jitter_y = 0.0f;
+  if (kernel_data.integrator.scrambling_distance < 1.0f) {
+    hash = kernel_data.integrator.seed;
+
+    jitter_x = cmj_randfloat_simple_dist(
+        dimension, rng_hash, kernel_data.integrator.scrambling_distance);
+    jitter_y = cmj_randfloat_simple_dist(
+        dimension + 1, rng_hash, kernel_data.integrator.scrambling_distance);
+  }
+
   /* Perform a shuffle on the sample number to reorder the samples. */
 #ifdef _SIMPLE_HASH_
-  const uint rv = cmj_hash_simple(dimension, rng_hash);
+  const uint rv = cmj_hash_simple(dimension, hash);
 #else /* Use a _REGULAR_HASH_. */
-  const uint rv = cmj_hash(dimension, rng_hash);
+  const uint rv = cmj_hash(dimension, hash);
 #endif
 #ifdef _XOR_SHUFFLE_
 #  warning "Using XOR shuffle."
@@ -137,7 +163,7 @@ ccl_device void pmj_sample_2D(KernelGlobals kg,
 
   /* Based on the sample number a sample pattern is selected and offset by the dimension. */
   const uint sample_set = s / NUM_PMJ_SAMPLES;
-  const uint d = (dimension + sample_set);
+  const uint d = dimension + sample_set;
   uint dim = d % NUM_PMJ_PATTERNS;
   int index = 2 * (dim * NUM_PMJ_SAMPLES + (s % NUM_PMJ_SAMPLES));
 
@@ -147,15 +173,15 @@ ccl_device void pmj_sample_2D(KernelGlobals kg,
 #ifndef _NO_CRANLEY_PATTERSON_ROTATION_
   /* Use Cranley-Patterson rotation to displace the sample pattern. */
 #  ifdef _SIMPLE_HASH_
-  float dx = cmj_randfloat_simple(d, rng_hash);
-  float dy = cmj_randfloat_simple(d + 1, rng_hash);
+  float dx = cmj_randfloat_simple(d, hash);
+  float dy = cmj_randfloat_simple(d + 1, hash);
 #  else
-  float dx = cmj_randfloat(d, rng_hash);
-  float dy = cmj_randfloat(d + 1, rng_hash);
+  float dx = cmj_randfloat(d, hash);
+  float dy = cmj_randfloat(d + 1, hash);
 #  endif
   /* Jitter sample locations and map back to the unit square [0 1]x[0 1]. */
-  float sx = fx + dx;
-  float sy = fy + dy;
+  float sx = fx + dx + jitter_x;
+  float sy = fy + dy + jitter_y;
   sx = sx - floorf(sx);
   sy = sy - floorf(sy);
 #else



More information about the Bf-blender-cvs mailing list