Transparent MeshBasicMaterial Darkens During Shader-Based Texture Transition

Problem Description:

Hello Three.js community,

I’m encountering a persistent issue with my card animation project, and I’m hoping to get some insights or solutions.

When my cards transition between textures (implemented with a ShaderMaterial), they briefly appear darker or have a noticeable darkening flicker. After the transition, the card returns to its original brightness. This darkening effect is not desired.

Here is a live example demonstrating the issue: https://codepen.io/WAKFLE/pen/VYLqyLE

Any guidance or suggestions on why this darkening occurs during the transparent shader transition would be greatly appreciated!

Thank you for your time and help.
2025-06-25 02-53-07

Your jsfiddle didn’t work for me.. it was choking on not finding players.json

But if i was to hazard a guess:
I think your transitionMaterial isn’t implementing the srgb colorspace conversion, whereas the regular shader you have, .. is.

Maybe adding the following after you write gl_FragColor in your transitionShader:

	gl_FragColor = linearToOutputTexel( gl_FragColor );
1 Like

Yeh like manthrax said it’s probably color space inconsistencies during the shader transition effect, When you switch from MeshBasicMaterial to your custom ShaderMaterial, the shader performs texture sampling and mixing in linear color space, but the textures are stored in sRGB color space. This mismatch causes the darkening effect. That’s my guess and if it’s correct then manthax gl_FragColor output line would work.

1 Like

Thanks for the comment. But I tried modifying it as you said, but when the card transitions, it suddenly becomes transparent. I modified it on the codepen linked above. Could you please check it?

Your fiddle doesn’t work since it can’t find players.json:

So the original code in your codepen throws player.json file not found error and also for the textures so I remake it using a single texture and fake player json list, the remake is not fancy but can you check if this is correct?, what I basically change is applying linearToOutputTexel only for the color

gl_FragColor = vec4(linearToOutputTexel(color).rgb, mix(tex1.a, tex2.a, sweep));:

Here’s the link

1 Like

Sorry for the late reply. Yes, that’s correct. I’ll give you my zip file, can you check it?

ok so replace your fragment shader with this:

fragmentShader: `
    uniform sampler2D texture1;
    uniform sampler2D texture2;
    uniform float mixRatio;
    varying vec2 vUv;
     // Three.js의 색상 관리 함수를 사용하기 위해 필요한 내장 함수 선언
     // Removed  "#include <colorspace_pars_fragment>" it's not important
     void main() {
            vec4 tex1 = texture2D(texture1, vUv);
            vec4 tex2 = texture2D(texture2, vUv);
            // sweep effect: mixes the two textures based on mixRatio and vUv.y
            float sweep = smoothstep(mixRatio - 0.2, mixRatio + 0.2, vUv.y);
            // glow effect: glowing effect around mixRatio.
            float glow = exp(-100.0 * pow(vUv.y - mixRatio, 2.0)) * 0.2; // Original glow strength (0.2)
            vec4 color = mix(tex1, tex2, sweep);
            color.rgb += glow * vec3(1.0, 0.8, 0.3); // Yellow-orange glow effect (original color)
            // 최종 출력 전에 sRGB로 변환 (linearToOutputTexel 함수 사용)

            // FIX: Don't apply linearToOutputTexel to the entire vec4 output
            gl_FragColor = vec4(linearToOutputTexel(color).rgb, mix(tex1.a, tex2.a, sweep));
     }
`
1 Like

Wow That’s work Thx! :slight_smile:

1 Like

aight mate, all good. Happy Coding !

1 Like