[Bf-blender-cvs] [ee89f213de2] master: Cycles: improve many lights sampling using light tree

Weizhen Huang noreply at git.blender.org
Mon Dec 5 16:14:24 CET 2022


Commit: ee89f213de2ec810317141ed87b889981eb8c348
Author: Weizhen Huang
Date:   Fri Dec 2 19:04:00 2022 +0100
Branches: master
https://developer.blender.org/rBee89f213de2ec810317141ed87b889981eb8c348

Cycles: improve many lights sampling using light tree

Uses a light tree to more effectively sample scenes with many lights. This can
significantly reduce noise, at the cost of a somewhat longer render time per
sample.

Light tree sampling is enabled by default. It can be disabled in the Sampling >
Lights panel. Scenes using light clamping or ray visibility tricks may render
different as these are biased techniques that depend on the sampling strategy.

The implementation is currently disabled on AMD HIP. This is planned to be fixed
before the release.

Implementation by Jeffrey Liu, Weizhen Huang, Alaska and Brecht Van Lommel.

Ref T77889

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

M	intern/cycles/blender/addon/properties.py
M	intern/cycles/blender/addon/ui.py
M	intern/cycles/blender/sync.cpp
M	intern/cycles/device/device.cpp
M	intern/cycles/device/device.h
M	intern/cycles/device/hip/device.cpp
M	intern/cycles/kernel/CMakeLists.txt
M	intern/cycles/kernel/data_arrays.h
M	intern/cycles/kernel/data_template.h
M	intern/cycles/kernel/integrator/shade_surface.h
M	intern/cycles/kernel/integrator/shade_volume.h
M	intern/cycles/kernel/integrator/state_template.h
M	intern/cycles/kernel/light/area.h
M	intern/cycles/kernel/light/background.h
M	intern/cycles/kernel/light/distant.h
M	intern/cycles/kernel/light/distribution.h
M	intern/cycles/kernel/light/point.h
M	intern/cycles/kernel/light/sample.h
M	intern/cycles/kernel/light/spot.h
A	intern/cycles/kernel/light/tree.h
M	intern/cycles/kernel/light/triangle.h
M	intern/cycles/kernel/types.h
M	intern/cycles/scene/CMakeLists.txt
M	intern/cycles/scene/integrator.cpp
M	intern/cycles/scene/integrator.h
M	intern/cycles/scene/light.cpp
M	intern/cycles/scene/light.h
A	intern/cycles/scene/light_tree.cpp
A	intern/cycles/scene/light_tree.h
M	intern/cycles/scene/object.cpp
M	intern/cycles/scene/scene.cpp
M	intern/cycles/scene/scene.h

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

diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 3f3fae32f40..fe8a29200f0 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -503,6 +503,12 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
         default='MULTIPLE_IMPORTANCE_SAMPLING',
     )
 
+    use_light_tree: BoolProperty(
+        name="Light Tree",
+        description="Sample multiple lights more efficiently based on estimated contribution at every shading point",
+        default=True,
+    )
+
     min_light_bounces: IntProperty(
         name="Min Light Bounces",
         description="Minimum number of light bounces. Setting this higher reduces noise in the first bounces, "
@@ -644,7 +650,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
 
     transparent_max_bounces: IntProperty(
         name="Transparent Max Bounces",
-        description="Maximum number of transparent bounces. This is independent of maximum number of other bounces ",
+        description="Maximum number of transparent bounces. This is independent of maximum number of other bounces",
         min=0, max=1024,
         default=8,
     )
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 4f5edd469be..d0d66d09442 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -383,7 +383,6 @@ class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
         col = layout.column(align=True)
         col.prop(cscene, "min_light_bounces")
         col.prop(cscene, "min_transparent_bounces")
-        col.prop(cscene, "light_sampling_threshold", text="Light Threshold")
 
         for view_layer in scene.view_layers:
             if view_layer.samples > 0:
@@ -392,6 +391,31 @@ class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
                 break
 
 
+class CYCLES_RENDER_PT_sampling_lights(CyclesButtonsPanel, Panel):
+    bl_label = "Lights"
+    bl_parent_id = "CYCLES_RENDER_PT_sampling"
+    bl_options = {'DEFAULT_CLOSED'}
+
+    def draw_header(self, context):
+        layout = self.layout
+        scene = context.scene
+        cscene = scene.cycles
+
+    def draw(self, context):
+        layout = self.layout
+        layout.use_property_split = True
+        layout.use_property_decorate = False
+
+        scene = context.scene
+        cscene = scene.cycles
+
+        col = layout.column(align=True)
+        col.prop(cscene, "use_light_tree")
+        sub = col.row()
+        sub.prop(cscene, "light_sampling_threshold", text="Light Threshold")
+        sub.active = not cscene.use_light_tree
+
+
 class CYCLES_RENDER_PT_subdivision(CyclesButtonsPanel, Panel):
     bl_label = "Subdivision"
     bl_options = {'DEFAULT_CLOSED'}
@@ -2365,6 +2389,7 @@ classes = (
     CYCLES_RENDER_PT_sampling_render_denoise,
     CYCLES_RENDER_PT_sampling_path_guiding,
     CYCLES_RENDER_PT_sampling_path_guiding_debug,
+    CYCLES_RENDER_PT_sampling_lights,
     CYCLES_RENDER_PT_sampling_advanced,
     CYCLES_RENDER_PT_light_paths,
     CYCLES_RENDER_PT_light_paths_max_bounces,
diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp
index a085202200f..f8be1b210b8 100644
--- a/intern/cycles/blender/sync.cpp
+++ b/intern/cycles/blender/sync.cpp
@@ -347,7 +347,14 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background)
     integrator->set_motion_blur(view_layer.use_motion_blur);
   }
 
-  integrator->set_light_sampling_threshold(get_float(cscene, "light_sampling_threshold"));
+  bool use_light_tree = get_boolean(cscene, "use_light_tree");
+  integrator->set_use_light_tree(use_light_tree);
+  integrator->set_light_sampling_threshold(
+      (use_light_tree) ? 0.0f : get_float(cscene, "light_sampling_threshold"));
+
+  if (integrator->use_light_tree_is_modified()) {
+    scene->light_manager->tag_update(scene, LightManager::UPDATE_ALL);
+  }
 
   SamplingPattern sampling_pattern = (SamplingPattern)get_enum(
       cscene, "sampling_pattern", SAMPLING_NUM_PATTERNS, SAMPLING_PATTERN_PMJ);
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index 6aef5458246..ff7e46d48ab 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -351,6 +351,7 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
   info.num = 0;
 
   info.has_nanovdb = true;
+  info.has_light_tree = true;
   info.has_osl = true;
   info.has_guiding = true;
   info.has_profiling = true;
@@ -399,6 +400,7 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
 
     /* Accumulate device info. */
     info.has_nanovdb &= device.has_nanovdb;
+    info.has_light_tree &= device.has_light_tree;
     info.has_osl &= device.has_osl;
     info.has_guiding &= device.has_guiding;
     info.has_profiling &= device.has_profiling;
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index 11d693cb25b..b9308dc8949 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -65,6 +65,7 @@ class DeviceInfo {
   int num;
   bool display_device;        /* GPU is used as a display device. */
   bool has_nanovdb;           /* Support NanoVDB volumes. */
+  bool has_light_tree;        /* Support light tree. */
   bool has_osl;               /* Support Open Shading Language. */
   bool has_guiding;           /* Support path guiding. */
   bool has_profiling;         /* Supports runtime collection of profiling info. */
@@ -84,6 +85,7 @@ class DeviceInfo {
     cpu_threads = 0;
     display_device = false;
     has_nanovdb = false;
+    has_light_tree = true;
     has_osl = false;
     has_guiding = false;
     has_profiling = false;
diff --git a/intern/cycles/device/hip/device.cpp b/intern/cycles/device/hip/device.cpp
index 3c9c73e7db0..518239f9877 100644
--- a/intern/cycles/device/hip/device.cpp
+++ b/intern/cycles/device/hip/device.cpp
@@ -137,6 +137,7 @@ void device_hip_info(vector<DeviceInfo> &devices)
     info.num = num;
 
     info.has_nanovdb = true;
+    info.has_light_tree = false;
     info.denoisers = 0;
 
     info.has_gpu_queue = true;
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index cb1f720af26..9dc343f597d 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -294,6 +294,7 @@ set(SRC_KERNEL_LIGHT_HEADERS
   light/point.h
   light/sample.h
   light/spot.h
+  light/tree.h
   light/triangle.h
 )
 
diff --git a/intern/cycles/kernel/data_arrays.h b/intern/cycles/kernel/data_arrays.h
index f2877e6c37f..6914a4642e9 100644
--- a/intern/cycles/kernel/data_arrays.h
+++ b/intern/cycles/kernel/data_arrays.h
@@ -60,6 +60,13 @@ KERNEL_DATA_ARRAY(KernelLight, lights)
 KERNEL_DATA_ARRAY(float2, light_background_marginal_cdf)
 KERNEL_DATA_ARRAY(float2, light_background_conditional_cdf)
 
+/* light tree */
+KERNEL_DATA_ARRAY(KernelLightTreeNode, light_tree_nodes)
+KERNEL_DATA_ARRAY(KernelLightTreeEmitter, light_tree_emitters)
+KERNEL_DATA_ARRAY(uint, light_to_tree)
+KERNEL_DATA_ARRAY(uint, object_lookup_offset)
+KERNEL_DATA_ARRAY(uint, triangle_to_tree)
+
 /* particles */
 KERNEL_DATA_ARRAY(KernelParticle, particles)
 
diff --git a/intern/cycles/kernel/data_template.h b/intern/cycles/kernel/data_template.h
index 3eda5582e46..06df7fe1e62 100644
--- a/intern/cycles/kernel/data_template.h
+++ b/intern/cycles/kernel/data_template.h
@@ -138,6 +138,7 @@ KERNEL_STRUCT_BEGIN(KernelIntegrator, integrator)
 /* Emission. */
 KERNEL_STRUCT_MEMBER(integrator, int, use_direct_light)
 KERNEL_STRUCT_MEMBER(integrator, int, use_light_mis)
+KERNEL_STRUCT_MEMBER(integrator, int, use_light_tree)
 KERNEL_STRUCT_MEMBER(integrator, int, num_lights)
 KERNEL_STRUCT_MEMBER(integrator, int, num_distant_lights)
 KERNEL_STRUCT_MEMBER(integrator, int, num_background_lights)
@@ -204,7 +205,6 @@ KERNEL_STRUCT_MEMBER(integrator, int, use_guiding_mis_weights)
 /* Padding. */
 KERNEL_STRUCT_MEMBER(integrator, int, pad1)
 KERNEL_STRUCT_MEMBER(integrator, int, pad2)
-KERNEL_STRUCT_MEMBER(integrator, int, pad3)
 KERNEL_STRUCT_END(KernelIntegrator)
 
 /* SVM. For shader specialization. */
diff --git a/intern/cycles/kernel/integrator/shade_surface.h b/intern/cycles/kernel/integrator/shade_surface.h
index 236510d593f..113ebb60c20 100644
--- a/intern/cycles/kernel/integrator/shade_surface.h
+++ b/intern/cycles/kernel/integrator/shade_surface.h
@@ -441,6 +441,7 @@ ccl_device_forceinline int integrate_surface_bsdf_bssrdf_bounce(
   /* Update path state */
   if (!(label & LABEL_TRANSPARENT)) {
     INTEGRATOR_STATE_WRITE(state, path, mis_ray_pdf) = bsdf_pdf;
+    INTEGRATOR_STATE_WRITE(state, path, mis_origin_n) = sd->N;
     INTEGRATOR_STATE_WRITE(state, path, min_ray_pdf) = fminf(
         unguided_bsdf_pdf, INTEGRATOR_STATE(state, path, min_ray_pdf));
   }
diff --git a/intern/cycles/kernel/integrator/shade_volume.h b/intern/cycles/kernel/integrator/shade_volume.h
index ec37cc4134b..4129b78feb0 100644
--- a/intern/cycles/kernel/integrator/shade_volume.h
+++ b/intern/cycles/kernel/integrator/shade_volume.h
@@ -685,15 +685,14 @@ ccl_device_forceinline void volume_integrate_heterogeneous(
 #  endif /* __DENOISING_FEATURES__ */
 }
 
-/* Path tracing: sample point on light and evaluate light shader, then
- * queue shadow ray to be traced. */
-ccl_device_forceinline bool integrate_volume_sample_light(
+/* Path tracing: sample point on light for equiangular sampling. */
+ccl_device_forceinline bool integrate_volume_equiangular_sample_light(
     KernelGlobals kg,
     IntegratorState state,
     ccl_private const Ray *ccl_restrict ray,
     ccl_private const ShaderData *ccl_restrict sd,
     ccl_private const RNGState *ccl_restrict rng_state,
-    ccl_private LightSample *ccl_restrict ls)
+    ccl_private float3 *ccl_restrict P)
 {
   /* Test if there is a light or BSDF that needs direct light. */
   if (!kernel_data.integrator.use_direct_light) {
@@ -705,6 +704,7 @@ ccl_device_forceinline bool integrate_volume_sample_light(
   const uint bounce = INTEGRATOR_STATE(state, path, bounce);
   const float2 rand_light = path_state_rng_2D(kg, rng_state, PRNG_LIGHT);
 
+  

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list