MeshLambertMaterial do not receive shadow from a SpotLight

Describe the bug

A Mesh with a MeshLambertMaterial does not receive shadows from a SpotLight. If I change the light to a DirectionalLight or change the Mesh to a MeshPhongMaterial, the shadow appears as I believe that is the expected.

To Reproduce

Steps to reproduce the behavior:

  1. Go to https://jsfiddle.net/catsvo8q/
  2. Check that the shadow does not appear in the plane.

Two approaches to see the shadow:

  1. Change line 55 to use a MeshPhongMaterial instead of a MeshLambertMaterial, and you can see the shadow.

Or:

  1. Change the line 62 to a DirectionalLight (const focusLight = new THREE.DirectionalLight(0xFFFFFF, 1);) instead of a SpotLight, and you can see the shadow.

Code

const renderer = new THREE.WebGLRenderer({antialias: true});
renderer.shadowMap.enabled = true;

const cube = new THREE.Mesh(
  new THREE.BoxBufferGeometry(),
  new THREE.MeshLambertMaterial({color: 0x4287f5})
);
cube.castShadow = true;

const floor = new THREE.Mesh(
  new THREE.PlaneBufferGeometry(10, 10),
  new THREE.MeshLambertMaterial({
    color: 0xFFFFFF,
    side: THREE.DoubleSide
  })
);
floor.rotation.x = THREE.MathUtils.degToRad(-90);
floor.receiveShadow = true;

const focusLight = new THREE.SpotLight(0xFFFFFF, 20, 10, 0.4);
focusLight.position.y = 4;
focusLight.castShadow = true;
focusLight.target = cube;

Live example

Expected behavior

A Mesh with a MeshLambertMaterial should display shadows from a SpotLight.

Screenshots

MeshLambertMaterial:
floor-with-lambert

MeshPhongMaterial:
floor-with-phong

Platform:

  • Device: Desktop
  • OS: Linux
  • Browser: Chrome
  • Three.js version: [dev, r0.126.1] (I checked the dev version directly from GitHub, and it has the same behavior.)

1 possible answer(s) on “MeshLambertMaterial do not receive shadow from a SpotLight

  1. See this SO answer.

    In the case of MeshLambertMaterial, the illumination calculation in only being performed at the four corners of the plane.

    Tessellate your geometry and you will be able to see what is happening:

    new THREE.PlaneBufferGeometry( 10, 10, 25, 25 )