Custom shader does not interact with light

Hello,

I spent a lot of time studying examples of how to use onBeforeCompile, in this forum and this guide (Extending three.js materials with GLSL), but I still don’t quite understand how the Replace works.
I made this fiddle with chromakey shader Based on this example using a phongMaterial to demonstrate the expected result
chromakey shader from webcam
The shader material code:

    chromakeyMaterial = new THREE.MeshPhongMaterial( { 
    		// color: 0x4080ff,
        map: webcamTexture,
        dithering: true,
        transparent: true,
        side: THREE.DoubleSide,
        //uniforms: THREE.UniformsLibs.Light
        //fog: true
     } );
     
   
     chromakeyMaterial.onBeforeCompile = shader => { 
        //shader.uniforms.time = { value: 0 };
        shader.uniforms.keyColor = { value: [0.0, 1.0, 0.0] };
        shader.uniforms.similarity = { value: 0.77 };
        shader.uniforms.smoothness = { value: 0.0 };

        shader.vertexShader = 'varying vec2 vUv;\n' + shader.vertexShader;
        shader.vertexShader = shader.vertexShader.replace(
          '#include <map_fragment>'
         );
         
        shader.fragmentShader = `
            uniform vec3 keyColor;
            uniform float similarity;
            uniform float smoothness;
            uniform vec2 vUv;
            uniform sampler2D map;
        ` + shader.fragmentShader;
        shader.fragmentShader = shader.fragmentShader.replace(
          '#include <map_fragment>',
           [
             ` vec4 videoColor = texture2D(map, vUv);

             float Y1 = 0.299 * keyColor.r + 0.587 * keyColor.g + 0.114 * keyColor.b;
             float Cr1 = keyColor.r - Y1;
             float Cb1 = keyColor.b - Y1;

             float Y2 = 0.299 * videoColor.r + 0.587 * videoColor.g + 0.114 * videoColor.b;
             float Cr2 = videoColor.r - Y2;
             float Cb2 = videoColor.b - Y2;

             float blend = smoothstep(similarity, similarity + smoothness, distance(vec2(Cr2, Cb2), vec2(Cr1, Cb1)));
             gl_FragColor = vec4(videoColor.rgb, videoColor.a * blend);
         }`
           ].join( '\n' )
         );

};

Since shaders are just strings in js - shader.replace behaves like this.

Because of that, keep in mind that this line of yours:

shader.vertexShader = shader.vertexShader.replace('#include <map_fragment>');

will replace #include <map_fragment> with undefined in the shader. Which may cause syntax errors.

1 Like