Row Rebel
Row Rebel

Reputation: 267

Three.js plane doesn't cast shadow

I'm stacking a plane and a sphere on top of a bigger plane, as seen in the following image

enter image description here

From WebGL inspector, it seems all three object are drawn in the shadowmap, but only the sphere is effectively appearing in the shadowmap, causing the smaller plane to never cast a shadow on the bigger one

Here's the scene construction

renderer.shadowMap.enabled = true

camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 5000);
camera.position.z = 600;
window.controls = new THREE.OrbitControls(camera, renderer.domElement);


light = new THREE.SpotLight(0xffffff, 1, 0, Math.PI / 2);
light.position.set(1, 1000, 1);
light.castShadow = true;
light.shadow = new THREE.LightShadow(new THREE.PerspectiveCamera(50, 1, 1, 5000));

scene.add(light);

var planeGeometry = new THREE.PlaneGeometry( innerWidth * 0.5, innerHeight * 0.5, 10, 10);
var plane = new THREE.Mesh( planeGeometry, new THREE.MeshPhongMaterial({ color: 0xffcccc }));
plane.rotation.x = -Math.PI / 2;
plane.castShadow = true;
plane.receiveShadow = true;
scene.add(plane);


var sphere = new THREE.SphereGeometry(100, 16, 8);
var spheremesh = new THREE.Mesh(sphere, new THREE.MeshPhongMaterial( ));
spheremesh.position.y = 200;
spheremesh.castShadow = true;
spheremesh.receiveShadow = true;
scene.add(spheremesh);

var planeGeometry1 = new THREE.PlaneGeometry( innerWidth, innerHeight, 10, 10);
var plane1 = new THREE.Mesh( planeGeometry1, new THREE.MeshPhongMaterial( ));
plane1.position.y = -250;
plane1.rotation.x = -Math.PI / 2;
plane1.castShadow = true;
plane1.receiveShadow = true;
scene.add(plane1);

Upvotes: 5

Views: 5053

Answers (1)

WestLangley
WestLangley

Reputation: 104783

By default, three.js culls front faces when generating shadow maps.

That means only back faces (from the point of view of the light) cast shadows. Culling front faces of your plane leaves nothing left to cast a shadow.

So one option is to replace your PlaneGeometry with a thin BoxGeometry, which has depth.

A second option is to set

material.shadowSide = THREE.DoubleSide;

In this case, your plane will cast a shadow, but there may be self-shadowing artifacts since you have both plane.castShadow = true and plane.receiveShadow = true.

Typically, the first option is the best option.

three.js r.151

Upvotes: 9

Related Questions