You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ThreeJS加载GLTF模型时法线与粗糙度纹理不显示求助

ThreeJS加载GLTF法线/粗糙度纹理不显示的解决方案

以下是针对该问题的排查和解决步骤:

1. 补充方向光/点光,解决光照不足问题

当前代码仅使用AmbientLight(环境光),这种无方向的均匀光照无法触发法线纹理的凹凸效果,也难以体现粗糙度纹理的质感。必须添加带有方向的光源:

// 在init函数中scene.add(light);之后添加
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2);
directionalLight.position.set(3, 5, 4); // 可调整位置以获得合适的光影角度
scene.add(directionalLight);

// 可选:开启阴影增强真实感
directionalLight.castShadow = true;
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;

2. 检查并修复材质参数

即使纹理已存在,默认参数可能被重置或未正确配置:

// 在load_gltf的回调函数中,scene.add(gltf.scene);之后添加
gltf.scene.traverse((obj) => {
  if (obj.isMesh && obj.material.isMeshStandardMaterial) {
    const mat = obj.material;
    // 恢复法线强度(默认应为(1,1),若被设为(0,0)则无效果)
    mat.normalScale.set(1, 1);
    // 让粗糙度纹理完全生效(将roughness设为1,由纹理控制粗糙度)
    mat.roughness = 1;
    // 若模型有金属度纹理,同理设置metalness为1
    // mat.metalness = 1;
    // 强制材质更新
    mat.needsUpdate = true;
  }
});

3. 修正纹理编码格式

法线、粗糙度纹理属于数据纹理,需使用线性编码而非sRGB编码,否则会显示异常:

// 同样在load_gltf的回调中添加
gltf.scene.traverse((obj) => {
  if (obj.isMesh && obj.material) {
    const mat = obj.material;
    if (mat.normalMap) mat.normalMap.encoding = THREE.LinearEncoding;
    if (mat.roughnessMap) mat.roughnessMap.encoding = THREE.LinearEncoding;
    mat.needsUpdate = true;
  }
});

4. 手动替换材质的正确姿势

若尝试手动替换为MeshStandardMaterial,需完整复制原材质的纹理和参数,避免遗漏:

gltf.scene.traverse((obj) => {
  if (obj.isMesh) {
    const oldMat = obj.material;
    const newMat = new THREE.MeshStandardMaterial({
      map: oldMat.map,
      normalMap: oldMat.normalMap,
      roughnessMap: oldMat.roughnessMap,
      normalScale: oldMat.normalScale.clone(), // 克隆向量避免引用问题
      roughness: oldMat.roughness,
      metalness: oldMat.metalness,
      color: oldMat.color.clone(),
      transparent: oldMat.transparent,
      opacity: oldMat.opacity
    });
    // 修正编码
    if (newMat.normalMap) newMat.normalMap.encoding = THREE.LinearEncoding;
    if (newMat.roughnessMap) newMat.roughnessMap.encoding = THREE.LinearEncoding;
    obj.material = newMat;
  }
});

优先尝试步骤1,因为环境光无法触发法线效果是最常见的原因。若仍未解决,依次检查后续步骤。

内容的提问来源于stack exchange,提问作者Limbo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 04:07:09