Fix #130829: Incorrect render result with light trees

The original report stumbled upon this issue with a more tricky
configuration when light linking is combined with light tress.
However, the actual contributing factor was a mesh with emission
shader which is not assigned to any triangles. This triggered a
bug in the BoundBox::transformed() which converted non-valid bounds
to bounds by performing per-corner growing.

Additionally fix incorrect handling of shared nodes which only
worked for leaf nodes. This was due to the fact how the measure
was accumulated: it is possible that add() is called with an empty
measure.

Pull Request: https://projects.blender.org/blender/blender/pulls/134699
This commit is contained in:
Sergey Sharybin
2025-02-18 13:11:46 +01:00
committed by Sergey Sharybin
parent 42ce049194
commit 24fbd71a56
4 changed files with 44 additions and 1 deletions

View File

@@ -157,6 +157,12 @@ struct LightTreeLightLink {
void add(const LightTreeLightLink &other)
{
/* other.set_membership is zero when expanding with an empty bucket: in this case there is no
* need to mark node as not shareable. */
if (other.set_membership == 0) {
return;
}
if (set_membership == 0) {
set_membership = other.set_membership;
shareable = other.shareable;
@@ -418,7 +424,7 @@ class LightTree {
return make_unique<LightTreeNode>(measure, bit_trial);
}
size_t num_emitters()
size_t num_emitters() const
{
return emitters_.size();
}

View File

@@ -33,6 +33,7 @@ set(SRC
kernel_camera_projection_test.cpp
render_graph_finalize_test.cpp
util_aligned_malloc_test.cpp
util_boundbox_test.cpp
util_ies_test.cpp
util_math_test.cpp
util_math_fast_test.cpp

View File

@@ -0,0 +1,30 @@
/* SPDX-FileCopyrightText: 2011-2025 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#include "util/boundbox.h"
#include "testing/testing.h"
#include "util/transform.h"
CCL_NAMESPACE_BEGIN
TEST(BoundBox, transformed)
{
{
const Transform tfm = transform_translate(make_float3(1, 2, 3));
const BoundBox orig_bounds(make_float3(-2, -3, -4), make_float3(3, 4, 5));
const BoundBox transformed_bounds = orig_bounds.transformed(&tfm);
EXPECT_LE(len(transformed_bounds.min - make_float3(-1, -1, -1)), 1e-6f);
EXPECT_LE(len(transformed_bounds.max - make_float3(4, 6, 8)), 1e-6f);
}
/* Non-valid boundbox should result in non-valid after transform. */
{
const Transform tfm = transform_scale(make_float3(1, 1, 1));
EXPECT_FALSE(BoundBox(BoundBox::empty).transformed(&tfm).valid());
}
}
CCL_NAMESPACE_END

View File

@@ -135,6 +135,12 @@ class BoundBox {
{
BoundBox result = BoundBox::empty;
/* Avoid transforming empty bounding box since the code below performs per-corner transform
* which will convert non-valid bounds to valid. */
if (!valid()) {
return result;
}
for (int i = 0; i < 8; i++) {
float3 p;