You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:20:00