Three.js加载图像纹理仅循环渲染显示,单次渲染无纹理问题求助
关于Three.js单次渲染纹理立方体显示黑色的问题解答
嘿,这个问题我刚入门Three.js的时候也踩过坑!咱们来一步步拆解原因和解决办法:
问题根源
你遇到的核心问题是纹理加载的异步特性:
THREE.TextureLoader().load()是异步执行的——调用这个方法后,浏览器会在后台下载图片,不会阻塞后续代码运行。- 当你第一次调用
renderer.render(scene, camera)时,纹理图片还没下载完成,MeshPhongMaterial因为没有可用的纹理数据,就会默认显示成黑色。 - 而用
requestAnimationFrame循环渲染时,等纹理加载完成后,后续的每一帧渲染都会用上已加载好的纹理,所以立方体就能正常显示了。 - 纯色材质不需要加载外部资源,所以单次渲染就能直接显示,这也是为什么纯色立方体没问题的原因。
解决办法
我们只需要利用TextureLoader.load()的回调函数,在纹理完全加载完成后再执行渲染操作就可以了。修改你的纹理加载代码如下:
var mapUrl = "images/monster.jpg"; var monsterMap = new THREE.TextureLoader().load(mapUrl, function(loadedTexture) { // 纹理加载完成后,触发渲染 renderer.render(scene, camera); });
这样即使只调用一次渲染,也能在纹理准备好之后正确显示立方体。如果需要在纹理加载完成后做更多操作(比如更新材质、调整场景),也可以在这个回调里完成,确保所有依赖纹理的操作都在资源就绪后执行。
修改后的完整代码示例
var renderer, scene, camera; function init() { scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 4000); camera.position.set(0, 0, 3); camera.lookAt(scene.position); scene.add(camera); renderer = new THREE.WebGLRenderer({antialias : true}); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setClearColor(0xEEEEEE, 1.0); var light = new THREE.DirectionalLight(0xffffff, 1.5); light.position.set(0, 0, 1); scene.add(light); var mapUrl = "images/monster.jpg"; var monsterMap = new THREE.TextureLoader().load(mapUrl, function() { // 纹理加载完成后执行渲染 renderer.render(scene, camera); }); var geometry = new THREE.CubeGeometry(1, 1, 1); var material = new THREE.MeshPhongMaterial({map:monsterMap}); var cube = new THREE.Mesh(geometry, material); cube.rotation.x = Math.PI / 5; cube.rotation.y = Math.PI / 5; scene.add(cube); document.getElementById("WebGL-output") .appendChild(renderer.domElement); } function run(){ renderer.render(scene, camera); requestAnimationFrame(run); } window.onload = init;
这样修改后,即使不调用run()函数,单次渲染也能正常显示带纹理的立方体啦!
内容的提问来源于stack exchange,提问作者Darryl
相关产品推荐
相关产品推荐

