From 35594f4b92fa4cbb5b848f447b7a3323e572b676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Mon, 9 May 2022 23:51:50 +0200 Subject: Fix T97985 EEVEE: Shader mixing not working correctly when reusing shader nodes This was caused by the `Closure` members being added to the final contribution more than once. The workaround is to clear the members once a closure has been added to the final contribution. I used `inout` on `Closure` inputs so that the render engine implementation of mix and add closure nodes can do its own thing. The nodegraph handling of inout was changed for this to work. --- .../draw/engines/eevee/shaders/closure_eval_surface_lib.glsl | 7 +++++-- .../draw/engines/eevee/shaders/closure_eval_volume_lib.glsl | 4 ++-- source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl | 4 ++-- source/blender/gpu/intern/gpu_node_graph.c | 4 ++-- .../gpu/shaders/material/gpu_shader_material_add_shader.glsl | 2 +- .../gpu/shaders/material/gpu_shader_material_mix_shader.glsl | 2 +- 6 files changed, 13 insertions(+), 10 deletions(-) diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl index f85ef4a89a4..0f5290a7c07 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl @@ -309,16 +309,19 @@ vec4 closure_to_rgba(Closure closure) return vec4(closure.radiance, 1.0 - saturate(avg(closure.transmittance))); } -Closure closure_add(Closure cl1, Closure cl2) +Closure closure_add(inout Closure cl1, inout Closure cl2) { Closure cl; cl.radiance = cl1.radiance + cl2.radiance; cl.transmittance = cl1.transmittance + cl2.transmittance; cl.holdout = cl1.holdout + cl2.holdout; + /* Make sure each closure is only added once to the result. */ + cl1 = CLOSURE_DEFAULT; + cl2 = CLOSURE_DEFAULT; return cl; } -Closure closure_mix(Closure cl1, Closure cl2, float fac) +Closure closure_mix(inout Closure cl1, inout Closure cl2, float fac) { /* Weights have already been applied. */ return closure_add(cl1, cl2); diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl index e450b8ad3c8..5e34d654cfd 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl @@ -92,7 +92,7 @@ vec4 closure_to_rgba(Closure closure) return vec4(0.0); } -Closure closure_mix(Closure cl1, Closure cl2, float fac) +Closure closure_mix(inout Closure cl1, inout Closure cl2, float fac) { Closure cl; cl.absorption = mix(cl1.absorption, cl2.absorption, fac); @@ -102,7 +102,7 @@ Closure closure_mix(Closure cl1, Closure cl2, float fac) return cl; } -Closure closure_add(Closure cl1, Closure cl2) +Closure closure_add(inout Closure cl1, inout Closure cl2) { Closure cl; cl.absorption = cl1.absorption + cl2.absorption; diff --git a/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl index 9698b5ea6f5..21d347942ca 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl @@ -87,8 +87,8 @@ Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection clearcoat, ClosureRefraction refraction); -Closure closure_add(Closure cl1, Closure cl2); -Closure closure_mix(Closure cl1, Closure cl2, float fac); +Closure closure_add(inout Closure cl1, inout Closure cl2); +Closure closure_mix(inout Closure cl1, inout Closure cl2, float fac); float ambient_occlusion_eval(vec3 normal, float distance, diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c index bc7ace792bb..b3a091ffbb0 100644 --- a/source/blender/gpu/intern/gpu_node_graph.c +++ b/source/blender/gpu/intern/gpu_node_graph.c @@ -611,7 +611,7 @@ bool GPU_link(GPUMaterial *mat, const char *name, ...) va_start(params, name); for (i = 0; i < function->totparam; i++) { - if (function->paramqual[i] != FUNCTION_QUAL_IN) { + if (function->paramqual[i] == FUNCTION_QUAL_OUT) { linkptr = va_arg(params, GPUNodeLink **); gpu_node_output(node, function->paramtype[i], linkptr); } @@ -669,7 +669,7 @@ static bool gpu_stack_link_v(GPUMaterial *material, } for (i = 0; i < function->totparam; i++) { - if (function->paramqual[i] != FUNCTION_QUAL_IN) { + if (function->paramqual[i] == FUNCTION_QUAL_OUT) { if (totout == 0) { linkptr = va_arg(params, GPUNodeLink **); gpu_node_output(node, function->paramtype[i], linkptr); diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_add_shader.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_add_shader.glsl index 99117400c57..3f42b6d9094 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_add_shader.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_add_shader.glsl @@ -1,4 +1,4 @@ -void node_add_shader(Closure shader1, Closure shader2, out Closure shader) +void node_add_shader(inout Closure shader1, inout Closure shader2, out Closure shader) { shader = closure_add(shader1, shader2); } diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_mix_shader.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_mix_shader.glsl index c303d21d7c1..00cfba3ca12 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_mix_shader.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_mix_shader.glsl @@ -1,4 +1,4 @@ -void node_mix_shader(float fac, Closure shader1, Closure shader2, out Closure shader) +void node_mix_shader(float fac, inout Closure shader1, inout Closure shader2, out Closure shader) { shader = closure_mix(shader1, shader2, fac); } -- cgit v1.2.3