Three.js新手求助:如何让GLTF模型投射阴影?
让GLTF模型在Three.js中投射阴影的正确做法
嘿,我刚看了你的代码,问题很明显——你把castShadow加错对象啦!你现在是给GLTFLoader加载器实例设置了这个属性,但castShadow是Three.js里Mesh对象的专属属性,加载器本身根本不吃这一套😅。
下面给你一步步讲正确的实现方式,连常见坑都给你补上:
第一步:先把全局阴影相关的基础配置拉满
阴影显示需要渲染器、灯光、接收阴影的物体三方配合,缺一不可:
- 渲染器开启阴影映射:
const renderer = new THREE.WebGLRenderer(); renderer.shadowMap.enabled = true; // 可选:开启软阴影,视觉效果更自然柔和 renderer.shadowMap.type = THREE.PCFSoftShadowMap; - 灯光开启阴影投射:
不是所有灯光都能投阴影,比如AmbientLight就不行,常用DirectionalLight(平行光)或者SpotLight(聚光灯)。以平行光为例:const dirLight = new THREE.DirectionalLight(0xffffff, 1); dirLight.position.set(5, 10, 7.5); // 调整位置确保能照到模型 dirLight.castShadow = true; // 关键:调整阴影相机的范围,不然阴影可能直接"隐身" dirLight.shadow.camera.left = -10; dirLight.shadow.camera.right = 10; dirLight.shadow.camera.top = 10; dirLight.shadow.camera.bottom = -10; scene.add(dirLight); - 添加接收阴影的地面/物体:
阴影得有地方显示才行,比如加个平面当地面:const groundGeo = new THREE.PlaneGeometry(20, 20); const groundMat = new THREE.MeshStandardMaterial({ color: 0xcccccc }); const ground = new THREE.Mesh(groundGeo, groundMat); ground.rotation.x = -Math.PI / 2; // 把平面翻过来当地面 ground.receiveShadow = true; scene.add(ground);
第二步:给GLTF模型的Mesh开启阴影投射
GLTF加载后返回的gltf.scene是一个Group容器,里面可能包含多个Mesh,所以需要遍历所有子物体,给每个Mesh单独设置castShadow:
const loader = new THREE.GLTFLoader(); loader.load('https://threejs.org/examples/models/gltf/Duck/glTF/Duck.gltf', function(gltf) { const model = gltf.scene; // 遍历模型的所有子元素,只给Mesh类型的对象开阴影 model.traverse(child => { if (child.isMesh) { child.castShadow = true; } }); scene.add(model); });
常见坑提醒
- 别用
MeshBasicMaterial:这种材质不受光照影响,自然也不会投射阴影,要用MeshStandardMaterial、MeshPhysicalMaterial这类支持光照的材质。 - 检查阴影相机范围:如果阴影没显示,大概率是灯光的阴影相机没覆盖到模型和地面,调整相机的left/right/top/bottom参数就行。
- 模型位置:确保模型在灯光的照射范围内,并且不在阴影相机的视野外。
内容的提问来源于stack exchange,提问作者Steve Hamlyn
相关产品推荐
相关产品推荐

