Spotlight in fragment shader

First of all, thanks to everyone for the effort needed to create this phenomenal library, maintenance it and answering questions.

Can anyone direct me to working example of using spotlight in fragment shader in Three.js or help me write on my own.

I defined spotlight in three.js (position, target.position, intensity, distance, angle and decay). How to applay this light in fragment shader?
In fragment shader, I need only to apply texture then spotlight (without shadow) and finally discard the black pixels.

js:

//spotlight
    this.spotLightMoon = new SpotLight("#ffffff");
    this.spotLightMoon.position.set(0, 0, -5);  
    this.spotLightMoon.target.position.set(0, 0, -40);        
    this.spotLightMoon.intensity = 0.8;
    this.spotLightMoon.distance = 30;
    this.spotLightMoon.angle = 0.9;
    this.spotLightMoon.decay = 0.5;
    this.spotLightMoon.visible = false;
  

 //define shaderMaterial
    let uniforms = {
      uTexture: { type: "t", value: this.moon3texture },
    } 
    uniforms = UniformsUtils.merge( [uniforms, UniformsLib["lights"] ]);

    const material = new ShaderMaterial({
      uniforms: uniforms,
      vertexShader: this.moon3Vertex,
      fragmentShader: this.moon3Fragment,
      lights: true
    });
    const geometry = new SphereGeometry(25, 32, 32);
    this.moon3 = new Mesh(geometry, material);


//later
       this.spotLightMoon.visible = true;
       this.moon3.material.needsUpdate = true; 


//Fragment Shader
  uniform sampler2D uTexture;
  varying vec2 vUv;

 void main() {
    vec4 baseColor = texture2D(uTexture, vUv);
    if(baseColor.g < 0.2)discard;
   gl_FragColor = vec4(baseColor.rgb, 1.0);
}

Enhancing custom shaders with light and shadows is tricky. Have you considered to just extend a built-in material type via Material.onBeforeCompile()? There is also an official example demonstrating this feature.

1 Like

If anyone needs it:

  const geometry = new SphereGeometry(25, 32, 32);
  const material = new MeshStandardMaterial({

   material.onBeforeCompile = function (shader) {
      shader.fragmentShader = shader.fragmentShader.replace(
        '#include <dithering_fragment>',
        [
          'if(gl_FragColor.r < 0.2) discard;',
          'gl_FragColor = vec4(gl_FragColor.rgb, gl_FragColor.a);'
        ].join('\n')
      );
    };

  this.moon3 = new Mesh(geometry, material);