[Bf-blender-cvs] [d44a623f8ef] soc-2022-many-lights-sampling: Cycles: improve shader emission estimation for light sampling

Brecht Van Lommel noreply at git.blender.org
Fri Nov 18 17:32:10 CET 2022


Commit: d44a623f8ef5bcb3f7d2a21cab4befef9ac4e97e
Author: Brecht Van Lommel
Date:   Thu Nov 17 18:47:07 2022 +0100
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rBd44a623f8ef5bcb3f7d2a21cab4befef9ac4e97e

Cycles: improve shader emission estimation for light sampling

* Support detection emission from Mix/Add shader nodes, which includes
  Principled BSDF as that generates an Emission + Add shader node.
* Add heuristic to exclude mesh light with low emission intensity from
  light sampling with the distribution or light tree. Shader sometimes
  have a bit of emission but treating them as a light source is not
  worth the memory/performance overhead.
* Materials now have an enum to set the emission sampling method, to be
  either None, Auto, Front, Back or Front & Back. This replace the
  previous "Multiple Importance Sample" option.
* For closed emissive meshes, setting this to Front can help reduce noise
  by ignoring emission from the mesh interior that is not visible.

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

M	intern/cycles/blender/addon/properties.py
M	intern/cycles/blender/addon/ui.py
M	intern/cycles/blender/addon/version_update.py
M	intern/cycles/blender/shader.cpp
M	intern/cycles/kernel/integrator/shade_surface.h
M	intern/cycles/kernel/types.h
M	intern/cycles/scene/geometry.cpp
M	intern/cycles/scene/light.cpp
M	intern/cycles/scene/light_tree.cpp
M	intern/cycles/scene/light_tree.h
M	intern/cycles/scene/object.cpp
M	intern/cycles/scene/osl.cpp
M	intern/cycles/scene/shader.cpp
M	intern/cycles/scene/shader.h
M	intern/cycles/scene/shader_graph.h
M	intern/cycles/scene/shader_nodes.cpp
M	intern/cycles/scene/shader_nodes.h
M	intern/cycles/scene/svm.cpp

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

diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 2fb0b2b702a..e6a88f58ce1 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -86,6 +86,14 @@ enum_sampling_pattern = (
     ('PROGRESSIVE_MULTI_JITTER', "Progressive Multi-Jitter", "Use Progressive Multi-Jitter random sampling pattern", 1),
 )
 
+enum_emission_sampling = (
+    ('NONE', 'None', "Do not use this surface as a light for sampling", 0),
+    ('AUTO', 'Auto', "Automatically determine if the surface should be treated as a light for sampling, based on estimated emission intensity", 1),
+    ('FRONT', 'Front', "Treat only front side of the surface as a light, usually for closed meshes whose interior is not visible", 2),
+    ('BACK', 'Back', "Treat only back side of the surface as a light for sampling", 3),
+    ('FRONT_BACK', 'Front and Back', "Treat surface as a light for sampling, emitting from both the front and back side", 4),
+)
+
 enum_volume_sampling = (
     ('DISTANCE',
      "Distance",
@@ -628,7 +636,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,
     )
@@ -1049,13 +1057,13 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
 
 class CyclesMaterialSettings(bpy.types.PropertyGroup):
 
-    sample_as_light: BoolProperty(
-        name="Multiple Importance Sample",
-        description="Use multiple importance sampling for this material, "
-        "disabling may reduce overall noise for large "
-        "objects that emit little light compared to other light sources",
-        default=True,
+    emission_sampling: EnumProperty(
+        name="Emission Sampling",
+        description="Sampling strategy for emissive surfaces",
+        items=enum_emission_sampling,
+        default="AUTO",
     )
+
     use_transparent_shadow: BoolProperty(
         name="Transparent Shadows",
         description="Use transparent shadows for this material if it contains a Transparent BSDF, "
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index ed94640b839..c9df6baa252 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1854,9 +1854,9 @@ class CYCLES_MATERIAL_PT_settings_surface(CyclesButtonsPanel, Panel):
         cmat = mat.cycles
 
         col = layout.column()
-        col.prop(cmat, "sample_as_light", text="Multiple Importance")
-        col.prop(cmat, "use_transparent_shadow")
         col.prop(cmat, "displacement_method", text="Displacement")
+        col.prop(cmat, "emission_sampling")
+        col.prop(cmat, "use_transparent_shadow")
 
     def draw(self, context):
         self.draw_shared(self, context.material)
diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py
index 12880496dfd..ea862da006c 100644
--- a/intern/cycles/blender/addon/version_update.py
+++ b/intern/cycles/blender/addon/version_update.py
@@ -99,7 +99,7 @@ def do_versions(self):
         library_versions.setdefault(library.version, []).append(library)
 
     # Do versioning per library, since they might have different versions.
-    max_need_versioning = (3, 0, 25)
+    max_need_versioning = (3, 5, 0)
     for version, libraries in library_versions.items():
         if version > max_need_versioning:
             continue
@@ -297,3 +297,8 @@ def do_versions(self):
                 cmat = mat.cycles
                 if not cmat.is_property_set("displacement_method"):
                     cmat.displacement_method = 'DISPLACEMENT'
+
+            if version <= (3, 5, 1):
+                cmat = mat.cycles
+                if not cmat.get("sample_as_light", True):
+                    cmat.emission_sampling = 'NONE'
diff --git a/intern/cycles/blender/shader.cpp b/intern/cycles/blender/shader.cpp
index dbc49df7f22..f25e98469fb 100644
--- a/intern/cycles/blender/shader.cpp
+++ b/intern/cycles/blender/shader.cpp
@@ -61,6 +61,12 @@ static DisplacementMethod get_displacement_method(PointerRNA &ptr)
       ptr, "displacement_method", DISPLACE_NUM_METHODS, DISPLACE_BUMP);
 }
 
+static EmissionSampling get_emission_sampling(PointerRNA &ptr)
+{
+  return (EmissionSampling)get_enum(
+      ptr, "emission_sampling", EMISSION_SAMPLING_NUM, EMISSION_SAMPLING_AUTO);
+}
+
 static int validate_enum_value(int value, int num_values, int default_value)
 {
   if (value >= num_values) {
@@ -1559,7 +1565,7 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
 
       /* settings */
       PointerRNA cmat = RNA_pointer_get(&b_mat.ptr, "cycles");
-      shader->set_use_mis(get_boolean(cmat, "sample_as_light"));
+      shader->set_emission_sampling_method(get_emission_sampling(cmat));
       shader->set_use_transparent_shadow(get_boolean(cmat, "use_transparent_shadow"));
       shader->set_heterogeneous_volume(!get_boolean(cmat, "homogeneous_volume"));
       shader->set_volume_sampling_method(get_volume_sampling(cmat));
diff --git a/intern/cycles/kernel/integrator/shade_surface.h b/intern/cycles/kernel/integrator/shade_surface.h
index fd31ac42946..7f8f07f5b59 100644
--- a/intern/cycles/kernel/integrator/shade_surface.h
+++ b/intern/cycles/kernel/integrator/shade_surface.h
@@ -112,11 +112,13 @@ ccl_device_forceinline void integrate_surface_emission(KernelGlobals kg,
   Spectrum L = surface_shader_emission(sd);
   float mis_weight = 1.0f;
 
+  const bool has_mis = !(path_flag & PATH_RAY_MIS_SKIP) &&
+                       (sd->flag & ((sd->flag & SD_BACKFACING) ? SD_MIS_BACK : SD_MIS_FRONT));
+
 #ifdef __HAIR__
-  if (!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS) &&
-      (sd->type & PRIMITIVE_TRIANGLE))
+  if (has_mis && (sd->type & PRIMITIVE_TRIANGLE))
 #else
-  if (!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS))
+  if (has_mis)
 #endif
   {
     mis_weight = light_sample_mis_weight_forward_surface(kg, state, path_flag, sd);
diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h
index 4d391674f1b..683dc26748c 100644
--- a/intern/cycles/kernel/types.h
+++ b/intern/cycles/kernel/types.h
@@ -788,8 +788,8 @@ enum ShaderDataFlag {
 
   /* Shader flags. */
 
-  /* direct light sample */
-  SD_USE_MIS = (1 << 16),
+  /* Use front side for direct light sampling. */
+  SD_MIS_FRONT = (1 << 16),
   /* Has transparent shadow. */
   SD_HAS_TRANSPARENT_SHADOW = (1 << 17),
   /* Has volume shader. */
@@ -818,12 +818,14 @@ enum ShaderDataFlag {
   SD_HAS_EMISSION = (1 << 29),
   /* Shader has raytracing */
   SD_HAS_RAYTRACE = (1 << 30),
-
-  SD_SHADER_FLAGS = (SD_USE_MIS | SD_HAS_TRANSPARENT_SHADOW | SD_HAS_VOLUME | SD_HAS_ONLY_VOLUME |
-                     SD_HETEROGENEOUS_VOLUME | SD_HAS_BSSRDF_BUMP | SD_VOLUME_EQUIANGULAR |
-                     SD_VOLUME_MIS | SD_VOLUME_CUBIC | SD_HAS_BUMP | SD_HAS_DISPLACEMENT |
-                     SD_HAS_CONSTANT_EMISSION | SD_NEED_VOLUME_ATTRIBUTES | SD_HAS_EMISSION |
-                     SD_HAS_RAYTRACE)
+  /* Use back side for direct light sampling. */
+  SD_MIS_BACK = (1 << 31),
+
+  SD_SHADER_FLAGS = (SD_MIS_FRONT | SD_HAS_TRANSPARENT_SHADOW | SD_HAS_VOLUME |
+                     SD_HAS_ONLY_VOLUME | SD_HETEROGENEOUS_VOLUME | SD_HAS_BSSRDF_BUMP |
+                     SD_VOLUME_EQUIANGULAR | SD_VOLUME_MIS | SD_VOLUME_CUBIC | SD_HAS_BUMP |
+                     SD_HAS_DISPLACEMENT | SD_HAS_CONSTANT_EMISSION | SD_NEED_VOLUME_ATTRIBUTES |
+                     SD_HAS_EMISSION | SD_HAS_RAYTRACE | SD_MIS_BACK)
 };
 
 /* Object flags. */
diff --git a/intern/cycles/scene/geometry.cpp b/intern/cycles/scene/geometry.cpp
index d1a3df851c1..8e831187477 100644
--- a/intern/cycles/scene/geometry.cpp
+++ b/intern/cycles/scene/geometry.cpp
@@ -271,7 +271,7 @@ void Geometry::tag_update(Scene *scene, bool rebuild)
   else {
     foreach (Node *node, used_shaders) {
       Shader *shader = static_cast<Shader *>(node);
-      if (shader->has_surface_emission) {
+      if (shader->emission_sampling != EMISSION_SAMPLING_NONE) {
         scene->light_manager->tag_update(scene, LightManager::EMISSIVE_MESH_MODIFIED);
         break;
       }
diff --git a/intern/cycles/scene/light.cpp b/intern/cycles/scene/light.cpp
index 547606bc1c7..e7f638459ae 100644
--- a/intern/cycles/scene/light.cpp
+++ b/intern/cycles/scene/light.cpp
@@ -163,7 +163,9 @@ bool Light::has_contribution(Scene *scene)
   if (light_type == LIGHT_BACKGROUND) {
     return true;
   }
-  return (shader) ? shader->has_surface_emission : scene->default_light->has_surface_emission;
+
+  const Shader *effective_shader = (shader) ? shader : scene->default_light;
+  return !is_zero(effective_shader->emission_estimate);
 }
 
 /* Light Manager */
@@ -257,7 +259,7 @@ bool LightManager::object_usable_as_light(Object *object)
    */
   foreach (Node *node, geom->get_used_shaders()) {
     Shader *shader = static_cast<Shader *>(node);
-    if (shader->get_use_mis() && shader->has_surface_emission) {
+    if (shader->emission_sampling != EMISSION_SAMPLING_NONE) {
       return true;
     }
   }
@@ -295,7 +297,7 @@ void LightManager::device_update_distribution(Device *device,
     if (light->is_enabled) {
       if (light_tree_enabled) {
         /* -prim_id - 1 is a light source index. */
-        LightTreePrimitive light_prim(scene, ~device_light_index, scene_light_index, false);
+        LightTreePrimitive light_prim(scene, ~device_light_index, scene_light_index);
 
         /* Distant lights get added to a separate vector. */
         if (light->light_type == LIGHT_DISTANT || light->light_type == LIGHT_BACKGROUND) {
@@ -320,8 +322,6 @@ void LightManager::device_update_distribution(Device *device,
 
   /* Similarly, we also want to keep track of the index of triangles that are emissive. */
   int object_id = 0;
-  /* TODO: add an option in the UI */
-  bool is_double_sided = true;
   foreach (Object *o

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list