I am relatively new to Three.js. But all my research regarding this issue has ended in a mute point. I have loaded in to my scene a gLTF model, and although all the meshes do reflect a sense of shadows, they do not cast shadows on the other meshes in the scene. I am using a spotlight to emulate a desk lamp. Also, despite ensuring that all castShadows and receiveShadows nodes are set to ‘true’, I am still unable to emulate true lighting atmosphere. Please see code snippet below for more detail.
let renderer = new THREE.WebGLRenderer( { canvas: document.getElementById( 'mainBody' ), antialias: true } );
renderer.setClearColor( 0x000000 );
renderer.setPixelRatio( window.devicePicelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap
renderer.gammaOutput = true;
renderer.gammaFactor = 2.2;
window.addEventListener( 'resize', onWindowResize, false );
let camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 3000 );
camera.position.x = 800;
camera.position.y = 350;
camera.position.z = 500;
let controls = new THREE.OrbitControls( camera );
// camera.position.set(0, 0, 0);
controls.update();
let scene = new THREE.Scene();
function addLights() {
let light1 = new THREE.SpotLight( 0xffffff, 0.8 ); //desklamp spotlight
light1.name = 'Desk Lamp';
light1.penumbra = 0.3;
light1.position.set( 263, 173, 420 );
light1.target.position.set( 300, 140, 420 );
light1.angle = Math.PI * 3;
light1.castShadow = true;
light1.receiveShadow = true;
light1.shadow.camera.near = 0.5; // default
light1.shadow.camera.far = 350 // default
light1.shadow.mapSize.width = 512; // default
light1.shadow.mapSize.height = 512; // default
scene.add( light1 );
scene.add( light1.target );
let helper = new THREE.CameraHelper ( light1.shadow.camera );
scene.add( helper );
// let light2 = new THREE.AmbientLight( 0xffffff, 0.1 ); used for testing light
// light2.position.set( 800, 200, 800 );
// scene.add( light2 );
}
addLights();
var loader = new THREE.GLTFLoader();
loader.load( 'assets/scene.gltf', function ( gltf ) { //model from sketchfab
gltf.scene.name = 'study';
gltf.scene.position.x = 0;
gltf.scene.position.y = 0;
gltf.scene.position.z = 1000;
gltf.scene.traverse( function( child ){ child.castShadow = true; } );
gltf.scene.traverse( function( child ){ child.receiveShadow = true; } );
scene.add( gltf.scene );
console.log( scene );
}, undefined, function ( error ) {
console.log( error );
} );
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
P.S. Apologies for the format if incorrect. Still new to this. Any advice for future posts welcome.
Without a live example I can only provide some basic suggestions.
Ensure that the shadow frustum of your camera is large enough so all shadow casting and receiving objects are actually contained in it. Since you are already using CameraHelper, it should be easy to verify this.
Use the ambient light not only for debugging/testing. A scene with just a spot light looks often very weird.
Your traverse function can be optimized. You don’t have to do it two times. Try it like so:
Checked the frustam and confirmed all should be casting within the lights range.
Thanks for the tip on the ambient light. I will keep that in mind during the development.
I have optimized my traverse function as you recommended. In doing so, I found that the model is not a mesh. This could potentially be the cause of my lack of shadows. Unfortunately I have no idea on how to resolve this. Any suggestions?
Here is the model. Unfortunately, I was unable to include the textures as the file ended up too big to upload. As for the import into blender, I simply went file>import>gLTF and selected the gLTF file.
I understand that the scene still requires post processing etc. But on my scene, the shadows around the pages on the desk as well as the drawers don’t appear at all.
That’s exactly what I was looking for. Thank you so very much for assisting. As I understand from the code you added, you’ve converted the scene to a THREE.box3 object to represent the minimum bounding boxes and manipulated it from there. Is that correct?