Next.js中使用Three.js无法将纹理应用到球体的问题
解决Next.js中Three.js球体显示黑色无纹理的问题
核心问题分析
你遇到的黑色球体问题,大概率和纹理异步加载、渲染时机或者Next.js静态资源路径有关,下面是针对性的解决步骤:
解决办法
1. 处理纹理异步加载的渲染更新
TextureLoader.load()是异步操作,你当前只在初始化时调用了一次renderer.render(),此时纹理还没加载完成,球体自然显示黑色。要在纹理加载完成后触发重新渲染:
const textureLoader = new THREE.TextureLoader(); textureLoader.load( "/earth_texture.jpg", (texture) => { texture.colorSpace = THREE.SRGBColorSpace; // 加载完成后更新材质并触发渲染 material.map = texture; material.needsUpdate = true; renderer.render(scene, camera); }, undefined, (err) => { console.error("纹理加载失败:", err); } );
2. 检查Next.js静态资源路径
确保earth_texture.jpg放在项目根目录的public文件夹下,Next.js会把public内的资源作为静态资源暴露,此时/earth_texture.jpg的路径才会生效。如果图片放在子文件夹(比如public/textures/earth_texture.jpg),路径要对应改成/textures/earth_texture.jpg。
3. 添加渲染循环(可选但推荐)
如果需要球体动画或后续画面更新,用requestAnimationFrame创建渲染循环,纹理加载完成后会自动更新画面:
function animate() { requestAnimationFrame(animate); // 可在此添加球体旋转等动画逻辑 sphere.rotation.y += 0.005; renderer.render(scene, camera); } animate();
4. 材质初始化兜底(可选)
可以给材质设置默认颜色,避免加载前完全黑屏:
let material = new THREE.MeshPhongMaterial({ shininess: 100, color: 0x808080 // 灰色兜底 });
调整后的完整代码示例
const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, 1 / 1, 0.1, 100); camera.position.z = 20; // 灯光设置 const aLight = new THREE.AmbientLight(0xffffff, 0.1); const light = new THREE.DirectionalLight(0xffffff, 3); light.position.set(-10, 5, 5); scene.add(light); scene.add(aLight); const geometry = new THREE.SphereGeometry(10, 64, 64); // 先创建带兜底颜色的材质 let material = new THREE.MeshPhongMaterial({ shininess: 100, color: 0x808080 }); let sphere = new THREE.Mesh(geometry, material); sphere.castShadow = true; sphere.receiveShadow = true; scene.add(sphere); const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true }); renderer.setSize(500, 500); containerRef.current?.appendChild(renderer.domElement); // 加载纹理并更新材质 const textureLoader = new THREE.TextureLoader(); textureLoader.load( "/earth_texture.jpg", (texture) => { texture.colorSpace = THREE.SRGBColorSpace; material.map = texture; material.needsUpdate = true; }, undefined, (err) => { console.error("纹理加载失败:", err); } ); // 启动渲染循环 function animate() { requestAnimationFrame(animate); sphere.rotation.y += 0.005; renderer.render(scene, camera); } animate();
内容的提问来源于stack exchange,提问作者ruben
相关产品推荐
相关产品推荐

