Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Three.js plane doesn't cast shadow

Tags:

three.js

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);
like image 803
Row Rebel Avatar asked Jan 31 '23 01:01

Row Rebel


1 Answers

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

renderer.shadowMap.renderReverseSided = true; // default is true

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

renderer.shadowMap.renderSingleSided = false; // default is true

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.86

like image 154
WestLangley Avatar answered Mar 20 '23 04:03

WestLangley