MeshStandardMaterial贴图不显示的根本原因是未启用光照响应,必须配合DirectionalLight或EnvironmentLight;还需检查UV展开、纹理尺寸为2的幂、sRGB编码及normalMap格式等。
MeshStandardMaterial 为什么贴不上纹理?多数人卡在这一步:模型加载成功,但 map 贴图始终不显示,表面灰白或纯色。根本原因不是图片路径错,而是材质未启用光照响应——MeshStandardMaterial 是 PBR 材质,必须配合 DirectionalLight 或 EnvironmentLight 才能正确渲染纹理明暗细节。
map 纹理会“存在但不可见”,控制台无报错MeshBasicMaterial 倒是能立刻看到贴图,但它不响应光照,不适合真实感建模常见现象是贴图扭曲、镜像、局部重复——这几乎全是 UV 展开问题,和 Three.js 代码关系不大,需回溯建模软件(Blender / Maya)导出前的 UV 检查。
U → Smart UV Project 后务必进 UV Editing 工作区检查是否重叠、拉伸Include > UVs(glTF 默认包含,但某些插件会关掉)wireframe: true,再叠加 color: 0xff0000,观察网格与纹理对应关系真实项目中不会只用 map,PBR 流程需要多纹理协同。Three.js 支持直接赋值,但要注意通道和格式。
const textureLoader = new THREE.TextureLoader();
const baseColorMap = textureLoader.load('texture_base.jpg');
const roughnessMap = textureLoader.load('texture_roughness.jpg');
const normalMap = textureLoader.load('texture_normal.jpg');
// 注意:roughnessMap 必须和 baseColorMap 尺寸一致,且推荐使用单通道灰度图
// normalMap 需开启 .normalScale 并设为 Vector2(1, 1)
const material = new THREE.MeshStandardMaterial({
map: baseColorMap,
roughnessMap: roughnessMap,
normalMap: normalMap,
normalScale: new THREE.Vector2(1, 1),
metalness: 0.2 // 全局金属度,可配合 metalnessMap 进一步细化
});
roughnessMap 和 metalnessMap 必须是灰度图,Three.js 只读取 R 通道normalMap 必须是 OpenGL 格式(Y 向上),Blender 默认导出的是 DirectX 格式,需在 Blender 中勾选 Export > Tangent Space > Flip Y
texture.encoding = THREE.sRGBEncoding(baseColorMap)或 THREE.LinearEncoding(其他贴图),否则色彩发灰或过曝一个角色模型配 4–5 张 2K 纹理,未压缩下超 100MB,首屏加载慢、低端设备 OOM。关键不在代码逻辑,而在资源交付方式。
DRACOLoader 压缩几何体,用 KTX2Loader + MeshoptDecoder 加载 GPU-ready 的 .ktx2 纹理(体积比 JPEG 小 60%,支持 ASTC/BPTC)onLoad 回调里直接创建材质,先缓存 Texture 实例,复用同一张图给多个模型texture.minFilter = THREE.LinearMipmapLinearFilter 并生成 mipmap(texture.generateMipmaps = true),否则远处纹理闪烁或模糊renderer.physicallyCorrectLights = true,或者把 normalMap 当成 
map 去加载。别急着改 JS,先打开 Blender 检 UV。