diff --git a/src/testrender/shading.cpp b/src/testrender/shading.cpp index 113721554..28d1b7c3d 100644 --- a/src/testrender/shading.cpp +++ b/src/testrender/shading.cpp @@ -1208,17 +1208,19 @@ evaluate_layer_opacity(const ShaderGlobalsType& sg, float path_roughness, int stack_idx = 0; const ClosureColor* ptr_stack[STACK_SIZE]; Color3 weight_stack[STACK_SIZE]; - Color3 weight = Color3(1.0f); + // Track the active branch separately from completed branch contributions. + Color3 branch_weight = Color3(1.0f); + Color3 accumulated_weight = Color3(0.0f); while (closure) { switch (closure->id) { case ClosureColor::MUL: - weight *= closure->as_mul()->weight; + branch_weight *= closure->as_mul()->weight; closure = closure->as_mul()->closure; break; case ClosureColor::ADD: ptr_stack[stack_idx] = closure->as_add()->closureB; - weight_stack[stack_idx++] = weight; + weight_stack[stack_idx++] = branch_weight; closure = closure->as_add()->closureA; break; default: { @@ -1229,13 +1231,13 @@ evaluate_layer_opacity(const ShaderGlobalsType& sg, float path_roughness, const MxLayerParams* srcparams = comp->as(); closure = srcparams->top; ptr_stack[stack_idx] = srcparams->base; - weight_stack[stack_idx++] = weight * w; + weight_stack[stack_idx++] = branch_weight * w; break; } case REFLECTION_ID: case FRESNEL_REFLECTION_ID: { Reflection bsdf(*comp->as()); - weight *= w * bsdf.get_albedo(-sg.I); + branch_weight *= w * bsdf.get_albedo(-sg.I); closure = nullptr; break; } @@ -1243,7 +1245,7 @@ evaluate_layer_opacity(const ShaderGlobalsType& sg, float path_roughness, const MxDielectric::Data& params = *comp->as(); MxDielectric d(params, -sg.I, sg.backfacing, path_roughness); - weight *= w * (Color3(1) - d.filter_o(-sg.I).toRGB(0)); + branch_weight *= w * (Color3(1) - d.filter_o(-sg.I).toRGB(0)); closure = nullptr; break; } @@ -1257,13 +1259,13 @@ evaluate_layer_opacity(const ShaderGlobalsType& sg, float path_roughness, } MxGeneralizedSchlick d(params, -sg.I, sg.backfacing, path_roughness); - weight *= w * (Color3(1) - d.filter_o(-sg.I).toRGB(0)); + branch_weight *= w * (Color3(1) - d.filter_o(-sg.I).toRGB(0)); break; } case MxSheen::closureid(): { const MxSheen::Data& params = *comp->as(); MxSheen d(params, -sg.I, sg.backfacing, path_roughness); - weight *= w * (Color3(1) - d.filter_o(-sg.I).toRGB(0)); + branch_weight *= w * (Color3(1) - d.filter_o(-sg.I).toRGB(0)); closure = nullptr; break; } @@ -1273,12 +1275,15 @@ evaluate_layer_opacity(const ShaderGlobalsType& sg, float path_roughness, } } } - if (closure == nullptr && stack_idx > 0) { - closure = ptr_stack[--stack_idx]; - weight = weight_stack[stack_idx]; + if (closure == nullptr) { + accumulated_weight += branch_weight; + if (stack_idx > 0) { + closure = ptr_stack[--stack_idx]; + branch_weight = weight_stack[stack_idx]; + } } } - return weight; + return accumulated_weight; } OSL_HOSTDEVICE void @@ -1716,33 +1721,38 @@ process_background_closure(const ClosureColor* closure) int stack_idx = 0; const ClosureColor* ptr_stack[STACK_SIZE]; Color3 weight_stack[STACK_SIZE]; - Color3 weight = Color3(1.0f); + // Track the active branch separately from completed branch contributions. + Color3 branch_weight = Color3(1.0f); + Color3 accumulated_weight = Color3(0.0f); while (closure) { switch (closure->id) { case ClosureColor::MUL: { - weight *= closure->as_mul()->weight; + branch_weight *= closure->as_mul()->weight; closure = closure->as_mul()->closure; break; } case ClosureColor::ADD: { ptr_stack[stack_idx] = closure->as_add()->closureB; - weight_stack[stack_idx++] = weight; + weight_stack[stack_idx++] = branch_weight; closure = closure->as_add()->closureA; break; } case BACKGROUND_ID: { - weight *= closure->as_comp()->w; + branch_weight *= closure->as_comp()->w; closure = nullptr; break; } } - if (closure == nullptr && stack_idx > 0) { - closure = ptr_stack[--stack_idx]; - weight = weight_stack[stack_idx]; + if (closure == nullptr) { + accumulated_weight += branch_weight; + if (stack_idx > 0) { + closure = ptr_stack[--stack_idx]; + branch_weight = weight_stack[stack_idx]; + } } } - return weight; + return accumulated_weight; } OSL_HOSTDEVICE Color3 diff --git a/testsuite/render-background/envmap.osl b/testsuite/render-background/envmap.osl index 7e5906f05..11528a7a0 100644 --- a/testsuite/render-background/envmap.osl +++ b/testsuite/render-background/envmap.osl @@ -11,5 +11,6 @@ shader envmap(float Kb = 1, string filename = "") float tu = 0.5 + r * cos(radial); float tv = 0.5 - r * sin(radial); color c = texture(filename, tu, tv); - Ci = Kb * c * background(); + Ci = Kb * c * color(1, 1, 0) * background() + + Kb * c * color(0, 0, 1) * background(); } diff --git a/testsuite/render-mx-layer/layer_add.osl b/testsuite/render-mx-layer/layer_add.osl new file mode 100644 index 000000000..50ea7a7cf --- /dev/null +++ b/testsuite/render-mx-layer/layer_add.osl @@ -0,0 +1,18 @@ +// Copyright Contributors to the Open Shading Language project. +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + +surface layer_add(int distributed = 0) +{ + closure color red + = oren_nayar_diffuse_bsdf(N, color(1, 0, 0), 0.3); + closure color blue + = oren_nayar_diffuse_bsdf(N, color(0, 0, 1), 0.3); + closure color green + = oren_nayar_diffuse_bsdf(N, color(0, 1, 0), 0.3); + + if (distributed) + Ci = 0.5 * layer(red, green) + 0.5 * layer(blue, green); + else + Ci = layer(0.5 * red + 0.5 * blue, green); +} diff --git a/testsuite/render-mx-layer/ref/out_add.exr b/testsuite/render-mx-layer/ref/out_add.exr new file mode 100644 index 000000000..f74cdfbc8 Binary files /dev/null and b/testsuite/render-mx-layer/ref/out_add.exr differ diff --git a/testsuite/render-mx-layer/run.py b/testsuite/render-mx-layer/run.py index 5e7591b97..51d5915b9 100755 --- a/testsuite/render-mx-layer/run.py +++ b/testsuite/render-mx-layer/run.py @@ -8,5 +8,6 @@ hardfail = 0.05 idiff_program = "idiff" -outputs = [ "out.exr" ] +outputs = [ "out.exr", "out_add.exr" ] command = testrender("-r 160 120 -aa 6 scene.xml out.exr") +command += testrender("-r 160 120 -aa 6 scene_add.xml out_add.exr") diff --git a/testsuite/render-mx-layer/scene_add.xml b/testsuite/render-mx-layer/scene_add.xml new file mode 100644 index 000000000..0d6b0160c --- /dev/null +++ b/testsuite/render-mx-layer/scene_add.xml @@ -0,0 +1,20 @@ + + + + + shader envmap layer1; + + + + + param int distributed 0; + shader layer_add layer1; + + + + + param int distributed 1; + shader layer_add layer1; + + +