[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