Why does glb object does not cast or receive shadows but other objects do?

I have created a model in Blender and exported it as a glb file. I want this object to receive shadows in three.js which isn’t happening. So i’ve created two basic meshes, a cube (the big green one) and a floor. The floor creates a shadow out of the cube but not from the glb object. Why is this and what am I doing wrong? I have enable the shadows for the glb model but still it doesn’t work.

let mixer;

  	const clock = new THREE.Clock();
  	const container = document.getElementById( 'container' );

  	const renderer = new THREE.WebGLRenderer( { antialias: true } );
  	renderer.setPixelRatio( window.devicePixelRatio );
  	renderer.setSize( window.innerWidth, window.innerHeight );
  	renderer.outputEncoding = THREE.sRGBEncoding;
  	renderer.shadowMap.enabled = true;
  	renderer.shadowMap.type = THREE.BasicShadowMap;
  	container.appendChild( renderer.domElement );

  	//const pmremGenerator = new THREE.PMREMGenerator( renderer );

  	const scene = new THREE.Scene();
  	scene.background = new THREE.Color( 0x000000 );
  	//scene.environment = pmremGenerator.fromScene( new RoomEnvironment(), 0.0 ).texture;

  	const camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 100 );
  	camera.position.set( 5, 2, 8 );

  	const controls = new OrbitControls( camera, renderer.domElement );
  	controls.target.set( 0, 1, 0 );
  	controls.update();
  	controls.enablePan = false;
  	controls.enableDamping = true;

  	// Mesh
  	var mesh;
  	mesh = new THREE.Mesh(
  		new THREE.BoxGeometry(1, 1, 1),
  		new THREE.MeshPhongMaterial({color:0xff444, wireframe:false})
  	);

  	mesh.position.y += 1;
  	mesh.receiveShadow = true;
  	mesh.castShadow = true;
  	scene.add(mesh);

  	// Ambientlight

  	const ambientLight = new THREE.AmbientLight(0xffffff, 0.2);
  	scene.add(ambientLight);

  	// Pointlight

  	const light = new THREE.PointLight(0xffffff, 0.8, 18);
  	light.position.set(0, 3, 0);
  	light.castShadow = true;
  	light.shadow.camera.near = 0.1;
  	light.shadow.camera.far = 25;
  	scene.add(light);

  	// Meshfloor
  	var meshFloor;
  	meshFloor = new THREE.Mesh(
  		new THREE.PlaneGeometry(10, 10, 10, 10),
  		new THREE.MeshPhongMaterial({color: 0xffffff, wireframe:false})
  	);

  	meshFloor.rotation.x -= Math.PI / 2;
  	meshFloor.receiveShadow = true;
  	scene.add(meshFloor);

  	const dracoLoader = new DRACOLoader();
  	dracoLoader.setDecoderPath( 'js/libs/draco/gltf/' );

  	const loader = new GLTFLoader();
  	loader.setDRACOLoader( dracoLoader );
  	loader.load( 'sketch.glb', function ( gltf ) {

  		const model = gltf.scene;
  		model.position.set( 0, 0.5, 0 );
  		model.scale.set( 0.1, 0.1, 0.1 );

  		model.castShadow = true;
  		model.receiveShadow = true;

  		scene.add( model );

  		mixer = new THREE.AnimationMixer( model );
  		mixer.clipAction( gltf.animations[ 0 ] ).play();

  		animate();

  	}, undefined, function ( e ) {

  		console.error( e );

  	} );

when you load your glTF, in the load success callback, traverse it and set castShadow for each child mesh.

Example

gltf.scene.traverse(function (child) {
    if (child.isMesh) {
        child.castShadow = true
        child.receiveShadow = true
    }
})

I have an example here where I do multiple things on each child mesh.

2 Likes

Thank you, this helped me.

I’ve apply it and some of the shadows are showing lines on spots there shouldn’t be shadows? I’ve changed the shadowmaptype and also pointlight to directionallight and played with the lights position & shadow.camera.near settings and I’ve been able to minimalize it but there still some unwanted shadows with weird lines occuring.

Do you know why this is there? I’ve googled it and tried countless solutions but it doesn’t go away fully.

The light should come from the top if I understood well and there is no other object above the main object so I really don’t know where this lines are coming from…

Changes

FROM

renderer.shadowMap.type = THREE.BasicShadowMap;

TO

renderer.shadowMap.type = THREE.PCFSoftShadowMap;

AND

FROM

const light = new THREE.PointLight(0xffffff, 0.8, 18);
light.position.set(0, 3, 0);
light.castShadow = true;
light.shadow.camera.near = 0.1;
light.shadow.camera.far = 25;
scene.add(light);

TO

const light = new THREE.DirectionalLight( 0xffffff, 0.5, 100 );
light.position.set( 0, 10, 0 );
light.castShadow = true;
light.shadow.camera.near = 0.1;
scene.add( light );|

light.shadow.bias=0.02;
or
light.shadow.bias=-0.02;

1 Like

Thank you very much light.shadow.bias = -0.001; helped

I think baking shadows as AO map is a good option to make it soft and realistic.

1 Like