Three.js中GLB模型仅部分子网格投射阴影问题求助
GLB模型部分子网格无法投射阴影的排查方案
以下是针对问题的具体排查方向和代码解决方案:
1. 调整平行光阴影相机参数
平行光默认的阴影相机视锥体范围较小,若未覆盖到不投射阴影的子网格,会导致阴影被裁剪。你可以扩展相机范围并开启辅助线验证:
const sunLight = new THREE.DirectionalLight(0xe8c37b, 0.96); sunLight.position.set(10, 30, -60); sunLight.castShadow = true; // 扩展阴影相机视锥体范围(根据场景尺寸调整) sunLight.shadow.camera.left = -150; sunLight.shadow.camera.right = 150; sunLight.shadow.camera.top = 150; sunLight.shadow.camera.bottom = -150; sunLight.shadow.camera.near = 0.1; sunLight.shadow.camera.far = 600; // 提高阴影贴图分辨率(平衡性能与清晰度) sunLight.shadow.mapSize.set(2048, 2048); // 添加相机辅助线,直观查看视锥体是否覆盖所有模型 const shadowCamHelper = new THREE.CameraHelper(sunLight.shadow.camera); scene.add(shadowCamHelper); scene.add(sunLight);
2. 检查子网格材质类型
部分材质(如MeshBasicMaterial)不受光照影响,无法生成阴影。遍历模型时验证材质类型,必要时替换为支持光照的材质:
gltf.scene.traverse(function(child) { if (child.isMesh) { child.castShadow = true; child.receiveShadow = true; // 打印材质类型,排查是否存在不支持阴影的材质 console.log(`Mesh: ${child.name}, Material: ${child.material.type}`); // 测试用:强制替换为标准材质(临时验证) // if (child.material.type === "MeshBasicMaterial") { // child.material = new THREE.MeshStandardMaterial({ // color: child.material.color, // map: child.material.map // }); // } } });
3. 验证模型几何体与变换
- 检查子网格是否存在缩放为0、位置超出阴影相机范围的情况:
gltf.scene.traverse(function(child) { if (child.isMesh) { console.log(`Mesh: ${child.name}, Scale: ${child.scale.x}, Position: ${child.position.x}, ${child.position.y}, ${child.position.z}`); } }); - 几何体法线方向错误也会导致阴影失效,可重新计算法线:
gltf.scene.traverse(function(child) { if (child.isMesh) { child.geometry.computeVertexNormals(); // 若法线方向完全错误,可尝试翻转 // child.geometry.flipNormals(); } });
4. 确认渲染器阴影设置
确保渲染器已开启阴影映射,并使用合适的阴影类型:
renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 软阴影效果,可选
5. 排除天空/水面系统干扰
临时注释掉天空和水面相关代码,测试阴影是否恢复正常。若恢复,再逐步排查环境贴图或水面材质是否影响了阴影计算逻辑。
内容的提问来源于stack exchange,提问作者Noel
相关产品推荐
相关产品推荐

