I have been working on a Three.JS scene where I need to create an open-topped cylinder with two different colors for its front and inside surfaces.
To achieve this, I extended a new material class from THREE.MeshStandardMaterial
and made adjustments to the vertex and fragment shaders using the onBeforeCompile
hook.
In my fragment shader code snippet, I attempted to set the color based on whether the face is front or back-facing:
gl_FragColor = vec4(faceNormal.rgb, sampledDiffuseColor.w);
if(gl_FrontFacing == false) {
gl_FragColor = vec4(0.0, 0.0, 0.0, sampledDiffuseColor.w);
}
However, I noticed that the gl_FrontFacing
flag always remained true, even for the inner faces, which puzzled me as it should logically be false for those faces.
To simplify things, I updated the onBeforeCompile
hook by setting explicit colors for front and back-facing surfaces in both the vertex and fragment shaders.
onBeforeCompile(shader: any) {
shader.vertexShader = /* glsl */ `
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
shader.fragmentShader = /* glsl */`
void main() {
gl_FragColor = gl_FrontFacing ? vec4(1.0, 0.0, 0.0, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
}
`;
}
This caused both the front and back sides to appear red in the rendered image.
After troubleshooting further, I discovered that setting transparent: true
while creating the material was causing the issue. When I disabled transparency, the coloring worked correctly.
Although transparency is needed for the material, it conflicts with achieving the desired color effect inside the cylinder.
A full example with transparent enabled but incorrect inner color is provided below:
[Code Snippet Example]