three.js使用WebGLRenderer与灯光时TextureLoader纹理显示黑面问题
Three.js 立方体纹理映射贴图面显示纯黑色问题修复
问题现象
- 已将渲染器从
CanvasRenderer替换为WebGLRenderer,材质从MeshBasicMaterial替换为MeshPhongMaterial - 立方体无贴图的黄色纯色面渲染正常,绑定了外部纹理的面始终显示纯黑色
现有相关代码
渲染逻辑
const renderer = new THREE.WebGLRenderer(); function render() { renderer.render(scene, camera); }
灯光配置
const light = new THREE.PointLight("white", 1, 100); light.position.set(7, 10, 10); scene.add(light);
立方体与纹理加载逻辑
const loader = new THREE.TextureLoader(); const cube1geometry = new THREE.BoxGeometry(1, 1, 1); const textureCube1 = [ new THREE.MeshPhongMaterial({ map: loader.load("cat1.jpg") }), new THREE.MeshPhongMaterial({ color: "yellow" }), new THREE.MeshPhongMaterial({ map: loader.load("cat1.jpg") }), new THREE.MeshPhongMaterial({ color: "yellow" }), new THREE.MeshPhongMaterial({ color: "yellow" }), new THREE.MeshPhongMaterial({ color: "yellow" }), ]; const cube1mesh = new THREE.Mesh(cube1geometry, textureCube1); cube1mesh.position.set(0.0, 0.0, 2.0);
问题原因
TextureLoader.load()是异步接口,调用后会立刻返回空的纹理占位对象,实际图片资源需要等网络请求完成后才会填充到纹理对象中。当前代码仅在初始化阶段执行一次render(),纹理加载完成后没有触发重新渲染,带贴图的面就会一直停留在初始渲染的黑色状态。纯色材质不需要加载外部资源,初始化时就可以完成渲染,因此显示正常。
修复方法
- 优先使用渲染循环方案,适配绝大多数Three.js场景:修改渲染逻辑,加入
requestAnimationFrame实现持续渲染,资源加载、场景变换都会自动刷新画面
const renderer = new THREE.WebGLRenderer(); function render() { requestAnimationFrame(render); renderer.render(scene, camera); } // 启动渲染循环 render();
- 如果不想开持续渲染循环,可以在纹理加载完成的回调中手动触发一次重绘,同时复用纹理对象避免重复发起资源请求:
const loader = new THREE.TextureLoader(); const cube1geometry = new THREE.BoxGeometry(1, 1, 1); // 复用同一张纹理,减少不必要的资源请求 const catTexture = loader.load("cat1.jpg", () => { // 纹理加载完成后重新渲染一次 render(); }); const textureCube1 = [ new THREE.MeshPhongMaterial({ map: catTexture }), new THREE.MeshPhongMaterial({ color: "yellow" }), new THREE.MeshPhongMaterial({ map: catTexture }), new THREE.MeshPhongMaterial({ color: "yellow" }), new THREE.MeshPhongMaterial({ color: "yellow" }), new THREE.MeshPhongMaterial({ color: "yellow" }), ]; const cube1mesh = new THREE.Mesh(cube1geometry, textureCube1); cube1mesh.position.set(0.0, 0.0, 2.0);
- 额外排查项:如果修改后纹理仍为黑色,打开浏览器开发者工具控制台,检查是否存在图片404报错、跨域报错。本地开发时不要直接双击HTML文件通过file协议打开,需要启动本地静态服务访问页面,避免浏览器安全策略拦截本地资源加载。
内容的提问来源于stack exchange,提问作者dayday
相关产品推荐
相关产品推荐

