[Bf-blender-cvs] [c641caaf4d1] soc-2022-many-lights-sampling: Make light energy estimate work with Light Falloff node

Brecht Van Lommel noreply at git.blender.org
Wed Nov 16 19:27:31 CET 2022


Commit: c641caaf4d13c93946087dea626b078f5a8e4257
Author: Brecht Van Lommel
Date:   Wed Nov 16 16:12:47 2022 +0100
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rBc641caaf4d13c93946087dea626b078f5a8e4257

Make light energy estimate work with Light Falloff node

This is just one special case, but used in a few benchmark files so common
enough to try to handle while general shader graphs are difficult.

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

M	intern/cycles/scene/light_tree.cpp
M	intern/cycles/scene/shader.cpp
M	intern/cycles/scene/shader.h

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

diff --git a/intern/cycles/scene/light_tree.cpp b/intern/cycles/scene/light_tree.cpp
index 4838903522b..d65d661a9a3 100644
--- a/intern/cycles/scene/light_tree.cpp
+++ b/intern/cycles/scene/light_tree.cpp
@@ -197,37 +197,41 @@ void LightTreePrimitive::calculate_bcone(Scene *scene)
 
 void LightTreePrimitive::calculate_energy(Scene *scene)
 {
-  float3 strength = make_float3(0.0f);
-
   if (is_triangle()) {
     Object *object = scene->objects[object_id];
     Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
     Shader *shader = static_cast<Shader *>(mesh->get_used_shaders()[mesh->get_shader()[prim_id]]);
 
     /* to-do: need a better way to handle this when textures are used. */
-    if (!shader->is_constant_emission(&strength)) {
-      strength = make_float3(1.0f);
-    }
+    float3 shader_estimate;
+    shader->estimate_emission(shader_estimate);
 
     float area = triangle_area(vertices[0], vertices[1], vertices[2]);
-    strength *= area;
-    energy = scene->shader_manager->linear_rgb_to_gray(strength);
+    energy = area * scene->shader_manager->linear_rgb_to_gray(shader_estimate);
   }
   else {
     Light *lamp = scene->lights[object_id];
-    strength = lamp->get_strength();
     LightType type = lamp->get_light_type();
+
+    float3 strength = lamp->get_strength();
     if (type == LIGHT_AREA) {
       strength *= 0.25f; /* eval_fac scaling in `area.h` */
     }
     else if (type == LIGHT_SPOT || type == LIGHT_POINT) {
       strength *= 0.25f * M_1_PI_F; /* eval_fac scaling in `spot.h` and `point.h` */
     }
-    energy = scene->shader_manager->linear_rgb_to_gray(strength);
-    if (type == LIGHT_BACKGROUND) {
+    else if (type == LIGHT_BACKGROUND) {
       /* integrate over cosine-weighted hemisphere */
-      energy = lamp->get_average_radiance() * M_PI_F;
+      strength *= lamp->get_average_radiance() * M_PI_F;
+    }
+
+    if (lamp->get_shader()) {
+      float3 shader_estimate;
+      lamp->get_shader()->estimate_emission(shader_estimate);
+      strength *= shader_estimate;
     }
+
+    energy = scene->shader_manager->linear_rgb_to_gray(strength);
   }
 }
 
diff --git a/intern/cycles/scene/shader.cpp b/intern/cycles/scene/shader.cpp
index f176c19ec95..be613a790fa 100644
--- a/intern/cycles/scene/shader.cpp
+++ b/intern/cycles/scene/shader.cpp
@@ -217,8 +217,10 @@ Shader::~Shader()
   delete graph;
 }
 
-bool Shader::is_constant_emission(float3 *emission)
+bool Shader::estimate_emission(float3 &estimate)
 {
+  estimate = one_float3();
+
   /* If the shader has AOVs, they need to be evaluated, so we can't skip the shader. */
   foreach (ShaderNode *node, graph->nodes) {
     if (node->special_type == SHADER_SPECIAL_TYPE_OUTPUT_AOV) {
@@ -232,35 +234,38 @@ bool Shader::is_constant_emission(float3 *emission)
     return false;
   }
 
-  if (surf->link->parent->type == EmissionNode::get_node_type()) {
-    EmissionNode *node = (EmissionNode *)surf->link->parent;
-
-    assert(node->input("Color"));
-    assert(node->input("Strength"));
+  /* Only supports Emission/Background nodes with Light Fallof for now, not arbitrary
+   * shader graphs. */
+  ShaderNode *emission_node = surf->link->parent;
 
-    if (node->input("Color")->link || node->input("Strength")->link) {
-      return false;
-    }
-
-    *emission = node->get_color() * node->get_strength();
+  if (!(emission_node->type == EmissionNode::get_node_type() ||
+        emission_node->type == BackgroundNode::get_node_type())) {
+    return false;
   }
-  else if (surf->link->parent->type == BackgroundNode::get_node_type()) {
-    BackgroundNode *node = (BackgroundNode *)surf->link->parent;
-
-    assert(node->input("Color"));
-    assert(node->input("Strength"));
 
-    if (node->input("Color")->link || node->input("Strength")->link) {
-      return false;
-    }
+  ShaderInput *color_in = emission_node->input("Color");
+  ShaderInput *strength_in = emission_node->input("Strength");
+  assert(color_in);
+  assert(strength_in);
 
-    *emission = node->get_color() * node->get_strength();
+  if (!color_in->link) {
+    estimate *= emission_node->get_float3(color_in->socket_type);
+  }
+  if (!strength_in->link) {
+    estimate *= emission_node->get_float(strength_in->socket_type);
   }
   else {
-    return false;
+    ShaderNode *falloff_node = strength_in->link->parent;
+    if (falloff_node->type == LightFalloffNode::get_node_type()) {
+      ShaderInput *falloff_strength_in = falloff_node->input("Strength");
+      if (!falloff_strength_in->link) {
+        estimate *= falloff_node->get_float(falloff_strength_in->socket_type);
+      }
+    }
   }
 
-  return true;
+  const bool is_constant = !color_in->link && !strength_in->link;
+  return is_constant;
 }
 
 void Shader::set_graph(ShaderGraph *graph_)
@@ -532,7 +537,7 @@ void ShaderManager::device_update_common(Device * /*device*/,
 
     /* constant emission check */
     float3 constant_emission = zero_float3();
-    if (shader->is_constant_emission(&constant_emission))
+    if (shader->estimate_emission(constant_emission))
       flag |= SD_HAS_CONSTANT_EMISSION;
 
     uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
diff --git a/intern/cycles/scene/shader.h b/intern/cycles/scene/shader.h
index 69b22d2ad19..32af12df5d1 100644
--- a/intern/cycles/scene/shader.h
+++ b/intern/cycles/scene/shader.h
@@ -131,11 +131,12 @@ class Shader : public Node {
   Shader();
   ~Shader();
 
-  /* Checks whether the shader consists of just a emission node with fixed inputs that's connected
-   * directly to the output.
-   * If yes, it sets the content of emission to the constant value (color * strength), which is
-   * then used for speeding up light evaluation. */
-  bool is_constant_emission(float3 *emission);
+  /* Estimate emission of this shader based on the shader graph. This works only in very simple
+   * cases. But it helps improve light importance sampling in common cases.
+   *
+   * If the emission is fully constant, returns true, so that shader evaluation can be skipped
+   * entirely for a light. */
+  bool estimate_emission(float3 &estimate);
 
   void set_graph(ShaderGraph *graph);
   void tag_update(Scene *scene);



More information about the Bf-blender-cvs mailing list