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.
This commit is contained in:
Clément Foucault 2022-05-09 23:51:50 +02:00
parent 10865c8f34
commit 35594f4b92
Notes: blender-bot 2023-02-14 09:43:37 +01:00
Referenced by commit 11aa237858, Eevee: Fix GLSL compilation error.
Referenced by issue #98003, Regression: Crash in EEVEE when switched to material preview or viewport/final render
Referenced by issue #97985, Eevee: Shader mixing not working correctly when reusing shader nodes
6 changed files with 13 additions and 10 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}