A-Frame&Three.js给模型赋值颜色贴图后物体变白无AO和阴影问题
问题原因&修复方案
你的问题由几个常见的Three.js材质配置问题共同导致,按优先级逐一修改即可:
- 纹理异步加载问题
TextureLoader.load()是异步方法,你直接赋值给材质的时候纹理还没有完成加载,Three.js会默认使用1x1的白色纹理占位,这是你看到全白效果的核心原因,必须等纹理加载完成后再赋值给材质或者触发材质更新。 - AO贴图缺少第二套UV
Three.js的MeshStandardMaterial默认从第二套UV(uv2属性)采样AO贴图,绝大多数建模工具导出GLB时只会默认导出第一套UV(供颜色/法线贴图使用),没有uv2的情况下AO贴图会完全失效。 - 颜色贴图颜色空间配置缺失
常规的LDR颜色贴图需要手动指定sRGB颜色空间,否则会出现颜色偏灰、饱和度异常的问题。
修复后代码参考
const customMat = { schema: {}, init() { this.el.addEventListener('model-loaded', (e) => { const material = new THREE.MeshStandardMaterial() const texLoader = new THREE.TextureLoader() texLoader.crossOrigin = '' // 加载完成计数,确保两个纹理都加载完再更新材质 let loadedCount = 0 const checkAllLoaded = () => { if(loadedCount === 2) { e.detail.model.traverse((mesh) => { if (mesh.isMesh) { // 没有uv2的话把第一套uv复制给uv2 if(!mesh.geometry.attributes.uv2) { mesh.geometry.attributes.uv2 = mesh.geometry.attributes.uv } mesh.material = material mesh.material.needsUpdate = true } }) } } const mapColor = texLoader.load('assets/cover_color.jpg', () => { loadedCount++ checkAllLoaded() }) // 配置颜色贴图的颜色空间 mapColor.colorSpace = THREE.SRGBColorSpace material.map = mapColor const mapAO = texLoader.load('assets/cover_ao.jpg', () => { loadedCount++ checkAllLoaded() }) material.aoMap = mapAO material.aoMapIntensity = 1 }) }, } export {customMat}
额外排查点
如果修改后还是有问题,可以按以下顺序排查:
- 给
load方法加错误回调,确认纹理路径正确、没有跨域/加载失败问题 - 确认场景中存在至少一个
MeshStandardMaterial兼容的光源(方向光、点光源、环境光都可) - 如果是修改原有GLB材质失效,确认你遍历到的mesh是模型的实际可渲染节点,部分GLB会嵌套多个组节点,需要确认
mesh.isMesh判断生效
内容的提问来源于stack exchange,提问作者Stirk
相关产品推荐
相关产品推荐

