FarazzShaikh / THREE-CustomShaderMaterial

🧩 Extend Three.js standard materials with your own shaders!
https://farazzshaikh.github.io/THREE-CustomShaderMaterial/
MIT License
890 stars 56 forks source link

Accessing csm_FragColor values in if statement causes white rendering #50

Closed benedikt7 closed 7 months ago

benedikt7 commented 7 months ago

Hi!

I'm attempting to achieve a specific effect on my mesh, where objects beyond a certain distance have full opacity, and those nearer to the viewer than the threshold have reduced opacity. So far, it seems like a straightforward task. I've created a new CustomShaderMaterial, based on the existing material of the mesh:

const material = new CustomShaderMaterial({
    baseMaterial: child.material,
    fragmentShader: `
    void main() {
        if (csm_FragColor[0] > 0.0) {
            // Some operation
        }
    }
});

The issue arises when I try to access the csm_FragColor values (even without writing to them). Strangely, the mesh renders fully white. However, if I comment out or remove the if statement (or any other statement that accesses csm_FragColor), the rendering appears correct. Is this a bug, or am I overlooking something simple?

Thanks!

FarazzShaikh commented 7 months ago

This is a limitation of the library. Since we use simple string compare to determine if a keyword is used within a shader. If said keyword is used, it’s particular patch is injected

we make no distinction between assigning or accessing. We can’t without more complicated processing of the shader which would cause a performance hit

I’m working on a new version of the library where I may address it. But until then your best bet is to not use csm_FragColor but some other internal shader value

we are already tracking this issue on #48 so I will close this one. Feel free to leave more comments regardless

benedikt7 commented 7 months ago

Ahh, that makes sense. Thanks for clarifying! Now the shader works as expected, thank you very much!

FarazzShaikh commented 7 months ago

By the way, If you are attenuating with distance it would make more sense to use a uniform:

uniform float uDistance;

void main() {
    csm_DiffuseColor.a = clamp(MAX_DIST - uDistance, 0.0, 1.0);
}