经纬志
首页 / 实战手册 / three.js 渲染

模型加载出来是黑的,转一圈也看不见

先看结论

GLTFLoader 没有报错,进度条也走到了 100%,但屏幕上只有一个黑色剪影,完全看不出材质。

最后验证 2026-11-03 · 多技术栈 · 更新 2026-10-29 · 引用本文

现象

模型轮廓能看见,说明几何已进入场景;所有面都是纯黑, 旋转模型时亮度不变;控制台没有 THREE.WebGLRenderer 的错误。 材质类型为 MeshStandardMaterial。

原因

MeshStandardMaterial 属于物理材质,颜色来自光照计算结果。 场景里只有一个 AmbientLight 时,它只会把环境色均匀地乘到材质上, 若是默认的 0x404040 再加低强度,结果接近黑色。 更常见的情况是场景里根本没加任何光源,只在代码里看到了 new Scene()。

另一个独立原因是输出色彩空间。r152 之后默认走 sRGB 输出, 但旧代码仍在设置 outputEncoding,赋值不生效, 贴图看起来偏暗,容易被误判为“全黑”。

排查过程

  1. 把材质临时换成 MeshBasicMaterial,如果立刻可见,问题就是光照。
  2. 打印场景中的光源数量:scene.children.filter(o => o.isLight).length。
  3. 检查 renderer.outputColorSpace 的值是否为 SRGBColorSpace。
  4. 检查模型的 material.color 是否被代码改成了 0x000000。
gltf.scene.traverse(function (o) {
  if (o.isMesh) {
    console.log(o.name, o.material.type, o.material.color.getHexString());
  }
});

解决方案

给场景补齐方向光与环境光。物理材质至少需要一个有方向的光源才能出层次:

var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.outputColorSpace = THREE.SRGBColorSpace;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.0;

var scene = new THREE.Scene();
scene.background = new THREE.Color(0x1b1f24);

var hemi = new THREE.HemisphereLight(0xffffff, 0x444444, 1.5);
scene.add(hemi);

var dir = new THREE.DirectionalLight(0xffffff, 2.0);
dir.position.set(50, 80, 30);
scene.add(dir);

var loader = new THREE.GLTFLoader();
loader.load('/models/pump.glb', function (gltf) {
  scene.add(gltf.scene);
  renderer.render(scene, camera);
});

贴图偏暗时,给颜色贴图指定 sRGB 空间。数据贴图(法线、粗糙度)不能这样设:

gltf.scene.traverse(function (o) {
  if (!o.isMesh) return;
  var mat = o.material;
  if (mat.map) {
    mat.map.colorSpace = THREE.SRGBColorSpace;
    mat.map.needsUpdate = true;
  }
  mat.needsUpdate = true;
});

需要暂时确认几何是否正确,用基础材质覆盖全部网格:

var debugMat = new THREE.MeshBasicMaterial({ color: 0x00bcd4, wireframe: true });
gltf.scene.traverse(function (o) {
  if (o.isMesh) o.material = debugMat;
});

验证

换回原材质后模型应有明暗过渡,棱角处能看到高光。 把 dir.intensity 从 2 调到 0.5,画面亮度应随之下降,说明光照链路生效。 贴图颜色与设计稿一致,不出现整体偏灰。

容易被忽略的一点:glTF 里的 KHR_materials_unlit 材质本身不受光照, 如果模型一半亮一半黑,先查是不是只有部分网格用了 unlit,而不是整体光照缺失。

引用本文

经纬志(2026)。《模型加载出来是黑的,转一圈也看不见》。https://www.jingweizhi.com/cookbook/three-model-all-black.html(访问日期 2026-11-03)。