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

Three.js中纹理无法覆盖整个球体几何体的问题求助

解决Three.js球体纹理无法覆盖的问题

你在制作旋转月球时遇到的纹理无法覆盖整个球体的问题,主要由以下两点导致:

1. 变量拼写错误

动画函数里的moom.rotation.x是拼写错误,正确变量名应为moon。这个错误会触发JavaScript运行时异常,直接中断动画逻辑,进而导致纹理渲染异常。

2. 纹理包裹模式适配(可选)

虽然SphereGeometry默认自带适配整个球体的UV映射,但如果你的月球图片比例特殊,可手动设置纹理包裹模式确保完全覆盖:

moonTexture.wrapS = THREE.ClampToEdgeWrapping;
moonTexture.wrapT = THREE.ClampToEdgeWrapping;

修复后的完整代码

import React, { useEffect } from "react";
import * as THREE from "three";
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls"
import moonImage from "../../images/moon.jpg"

const Home = () => {
  useEffect(() => {
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 1, 1000);
    const canvas = document.querySelector(".homeCanvas");
    const renderer = new THREE.WebGLRenderer({canvas});
    // 初始化时设置画布尺寸,避免拉伸
    renderer.setSize(window.innerWidth, window.innerHeight);

    const textureLoader = new THREE.TextureLoader();
    const moonTexture = textureLoader.load(moonImage);
    // 设置纹理包裹模式,适配球体UV
    moonTexture.wrapS = THREE.ClampToEdgeWrapping;
    moonTexture.wrapT = THREE.ClampToEdgeWrapping;
   
    const moonGeo = new THREE.SphereGeometry(3, 64, 64);
    const moonMaterial = new THREE.MeshStandardMaterial({map: moonTexture});
    const moon = new THREE.Mesh(moonGeo, moonMaterial);
    scene.add(moon);
    
    const pointLight = new THREE.PointLight(0xffffff, 1);
    pointLight.position.x = 20;
    scene.add(pointLight);
    
    const controls = new OrbitControls(camera, renderer.domElement);
    camera.position.z = 15;

    function animate() {
        requestAnimationFrame(animate);
        // 修正拼写错误,正常驱动月球旋转
        moon.rotation.x += 0.01;
        moon.rotation.y += 0.01;
        renderer.render(scene, camera);
    }
    animate();

    // 监听窗口大小变化,动态调整画布和相机
    const handleResize = () => {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize(window.innerWidth, window.innerHeight);
    }
    window.addEventListener('resize', handleResize);

    // 组件卸载时清理资源,避免内存泄漏
    return () => {
      window.removeEventListener('resize', handleResize);
      controls.dispose();
      renderer.dispose();
    }
  }, []);

  return (
   <>
   <div className="home"> 
    <canvas className="homeCanvas"></canvas>
   </div>
   </>
  )
}

export default Home

额外优化点

  • 移除了animate函数中每帧重复调用renderer.setSize的逻辑,改为监听窗口resize事件触发调整,提升渲染性能。
  • 添加了组件卸载时的资源清理逻辑,避免内存泄漏。

内容的提问来源于stack exchange,提问作者Haris Akram

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 13:15:53