Multi-material models doesn't cast shadow

Hallo, when I assign more than one material on single mesh (in Blender), shadows doesn’t show. Why? I use gltfLoader. in attached image are two towers. First (which cast shadow) is with one material, other (which dont cast shadow) is with two materials.
How to solve this? Thanks!
SMAZAT

Could you share your code, and ideally a demo?

I cant send you demo, because I am loading local models, but code is here:

<html>
<html>
 <head>
  <script src="js/three.js/build/three.min.js"></script>
  <script src="js/three.js/examples/js/controls/OrbitControls.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
		<script src="js/three.js/examples/js/loaders/GLTFLoader.js"></script>
     
  <script type="text/javascript">
      var camera,scene,directionalLight;
   $(function() {
		const gltfLoader = new THREE.GLTFLoader();
    
    //scene
   scene = new THREE.Scene();
    //camera
    camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 1000 );
    camera.position.set(-5,-23,8);
    camera.lookAt(new THREE.Vector3( 0, 0, 0 ));
     
    //renderer
    var renderer = new THREE.WebGLRenderer();
    renderer.setSize( window.innerWidth, window.innerHeight );
 
    renderer.shadowMapEnabled = true;
    renderer.shadowMapSoft = true;
 
    //controls
    //var controls = new THREE.OrbitControls( camera, renderer.domElement );
       
    //show canvas
    $("#canvas-container").html(renderer.domElement);
     
    //lights
     
 //directional light
 directionalLight = new THREE.DirectionalLight(0xffffff,3);
 directionalLight.position.set(5, -1, 5);
  
 directionalLight.castShadow = true;
 directionalLight.shadowCameraVisible = true;
  
 directionalLight.shadowCameraNear = 0;
 directionalLight.shadowCameraFar = 15;
  
  
 scene.add(directionalLight);
 
     
 //spotlight
  
     var p1,p2,p3;
     p1={};
     p2={};
    //plane
    var geometry = new THREE.PlaneGeometry(2000, 1000);
    var material = new THREE.MeshPhongMaterial( { color: 0xcccccc } );
    var plane = new THREE.Mesh( geometry, material );
    plane.receiveShadow = true;
    scene.add(plane);
     

	gltfLoader.load('objects/m.glb', 
            function(gltf) {
              	const root = gltf.scene;
  			  p1.model = root.getObjectByName("Cube");
  			//p1.model.scale.set(scale,scale,scale);
					scene.add(p1.model);
					p1.model.castShadow = true;
					//p1.model.position.x=3;
					p1.model.receiveShadow = true;
					p1.model.rotation.x=1.55;
  				
      });
    
	gltfLoader.load('objects/n.glb', 
            function(gltf) {
              	const root = gltf.scene;
  			  p2.model = root.getObjectByName("Cube");
  			//p1.model.scale.set(scale,scale,scale);
					scene.add(p2.model);
					p2.model.castShadow = true;
					p2.model.position.y=7;
					p2.model.receiveShadow = true;
					p2.model.rotation.x=1.55;
  				
      });
    
   
   
    //render scene
    var render = function () {
     requestAnimationFrame(render);
     renderer.render(scene, camera);
    };
       
    render();
       
   });
      
  </script>
     
 </head>
 <body style="background: black">
     
  <div id="canvas-container" style="position: absolute; left:0px; top:0px"></div>
     
 </body>
</html>

Your multi-material model is represented as multiple objects when loaded. If you check p1.model.children I think you’ll find that it has meshes inside of it. If you open the JS console while looking at http://gltf-viewer.donmccurdy.com/ and open your model, you’ll see the full list of objects.

Additionally, large meshes may have to be split into multiple meshes when exported from Blender. Instead of expecting only a single mesh, traverse:

p1.model.position.set( ... );
p1.model.traverse(function(o) {
  if (o.isMesh) {
    o.castShadow = true;
    o.receiveShadow = true;
  }
});
scene.add(p1.model);
4 Likes

You are right, my model consist of more than one mesh. Solved, Thanks a lot!