From 56bfd56735bc07d799cb6a458710018d16264897 Mon Sep 17 00:00:00 2001 From: Alaska Date: Thu, 22 Feb 2024 19:06:22 +0100 Subject: [PATCH] Fix: Cycles incorrect rendering of certain negative strength lights This fixes an issue where lights that make use of constant negative strength emission shaders would render with the absolute of their strength. Pull Request: https://projects.blender.org/blender/blender/pulls/118541 --- intern/cycles/scene/light_tree.cpp | 6 ++++-- intern/cycles/scene/shader.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/intern/cycles/scene/light_tree.cpp b/intern/cycles/scene/light_tree.cpp index 486435048c4..04e34fbda50 100644 --- a/intern/cycles/scene/light_tree.cpp +++ b/intern/cycles/scene/light_tree.cpp @@ -108,7 +108,9 @@ LightTreeEmitter::LightTreeEmitter(Scene *scene, /* TODO: need a better way to handle this when textures are used. */ float area = triangle_area(vertices[0], vertices[1], vertices[2]); - measure.energy = area * average(shader->emission_estimate); + /* Use absolute value of emission_estimate so lights with negative strength are properly + * supported in the light tree. */ + measure.energy = area * average(fabs(shader->emission_estimate)); /* NOTE: the original implementation used the bounding box centroid, but triangle centroid * seems to work fine */ @@ -220,7 +222,7 @@ LightTreeEmitter::LightTreeEmitter(Scene *scene, /* Use absolute value of energy so lights with negative strength are properly supported in the * light tree. */ - measure.energy = fabsf(average(strength)); + measure.energy = average(fabs(strength)); light_set_membership = lamp->get_light_set_membership(); } diff --git a/intern/cycles/scene/shader.cpp b/intern/cycles/scene/shader.cpp index 72db06e2604..6666d2b3b90 100644 --- a/intern/cycles/scene/shader.cpp +++ b/intern/cycles/scene/shader.cpp @@ -264,7 +264,7 @@ void Shader::estimate_emission() } ShaderInput *surf = graph->output()->input("Surface"); - emission_estimate = fabs(output_estimate_emission(surf->link, emission_is_constant)); + emission_estimate = output_estimate_emission(surf->link, emission_is_constant); if (is_zero(emission_estimate)) { emission_sampling = EMISSION_SAMPLING_NONE; @@ -274,8 +274,9 @@ void Shader::estimate_emission() * using a lot of memory in the light tree and potentially wasting samples * where indirect light samples are sufficient. * Possible optimization: estimate front and back emission separately. */ - emission_sampling = (reduce_max(emission_estimate) > 0.5f) ? EMISSION_SAMPLING_FRONT_BACK : - EMISSION_SAMPLING_NONE; + emission_sampling = (reduce_max(fabs(emission_estimate)) > 0.5f) ? + EMISSION_SAMPLING_FRONT_BACK : + EMISSION_SAMPLING_NONE; } else { emission_sampling = emission_sampling_method;