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

THREE.js中SphereBufferGeometry使用ShaderMaterial的UV纹理包裹异常问题

问题根源

你代码的核心问题出在顶点着色器传递给片元着色器的vWave变量取值逻辑:

  • 你使用模型空间的pos.z(叠加噪声后的数值)作为vWave的数据源,而半径25的球体模型空间z坐标的取值范围是[-25, 25],只有赤道附近的顶点z值接近0,其他区域的z值绝对值都很大
  • 片元着色器里你直接给uv叠加了vWave * 0.25,相当于非赤道区域的纹理采样坐标被偏移了好几个单位,远远超出了uv的正常取值范围[0,1],自然只能看到赤道窄带的正常纹理。你之前调整纹理包裹参数无效,本质是这个偏移问题导致的,和纹理本身的包裹规则无关。

另外你顶点着色器还有一处无效代码:你修改了pos.z的值,但最后gl_Position计算用的还是原始的position变量,前面的pos修改完全没有生效。


修复方案

1. 修改顶点着色器逻辑

直接把噪声计算结果赋值给vWave,不要叠加模型本身的z坐标即可。如果想要无接缝的球面效果,建议用归一化的顶点坐标来生成噪声:

void main() {
  vUv = uv;

  float noiseFreq = 3.5;
  float noiseAmp = 0.15; 
  // 用归一化的球面坐标生成3D噪声,无接缝
  vec3 noisePos = normalize(position) * noiseFreq + vec3(uTime, 0.0, 0.0);
  float noiseVal = snoise(noisePos) * noiseAmp;
  vWave = noiseVal;

  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.);
}

如果不需要3D球面噪声,用uv生成噪声也可以:

vec3 noisePos = vec3(vUv.x * noiseFreq + uTime, vUv.y * noiseFreq, 0.0);

2. 调整片元着色器偏移幅度

现在vWave的取值范围是[-0.15, 0.15],可以根据你要的流动效果自由调整系数,不会再出现uv偏移过大的问题:

void main() {
  float wave = vWave * 0.2; // 可自行调整控制流动幅度
  vec3 texture = texture2D(uTexture, vUv + wave).rgb;
  gl_FragColor = vec4(texture, 1.);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 23:45:02