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

WebGL Shader实现球体渐变纹理时出现接缝与色块问题如何解决

球体平滑渐变着色解决方案

基础错误修复

你当前的着色器存在核心逻辑错误:varying变量仅能在顶点着色器中赋值,片元着色器没有内置的uv、position变量,不可在片元着色器中对varying变量重复赋值,这是你此前结果异常的核心原因之一。
修正后的基础代码如下:

顶点着色器

varying vec2 vUv;
varying vec3 vPosition;
varying vec3 vNormal; // 新增法向量传递用变量

void main () {
  vUv = uv;
  vPosition = position;
  vNormal = normal;
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 
}

片元着色器

varying vec2 vUv;
varying vec3 vPosition;
varying vec3 vNormal;

void main () {
  // 直接读取varying变量,不要重新赋值
  // 渐变逻辑写在此处
}

异常原因说明

  • UV接缝:球体UV展开本身在经度衔接处UV.x会从1跳变到0,直接用UV作为颜色分量必然出现硬边
  • position色块:模型空间position的x/y/z分量存在正负值,颜色分量小于0会被截断为0,大于1会被截断为1,8个坐标象限对应8块分界明显的色块
  • UV方案极点尖峰:球体南北极所有顶点的UV.y固定为0/1,但UV.x分布在0~1全区间,基于UV的计算会放大极点处的UV不连续性,导致尖峰效果

推荐平滑渐变实现方案

方案1:基于法向量的渐变(无瑕疵首选)

球体法向量是全局连续的单位向量,不存在接缝或尖峰,映射到颜色值域即可得到完全平滑的渐变效果,片元着色器代码:

void main () {
  // 把法向量从[-1,1]区间映射到颜色要求的[0,1]区间
  vec3 smoothColor = normalize(vNormal) * 0.5 + 0.5;
  gl_FragColor = vec4(smoothColor, 1.0);
}

方案2:基于球坐标的自定义渐变

如果需要自定义经度/纬度方向的渐变,可将位置坐标转成球坐标计算,避免UV接缝:

#define PI 3.14159265359
void main () {
  vec3 normPos = normalize(vPosition);
  // 计算经纬度并映射到[0,1]区间
  float longitude = (atan(normPos.z, normPos.x) + PI) / (2.0 * PI);
  float latitude = acos(normPos.y) / PI;
  // 示例:从上到下蓝到红渐变
  vec3 customColor = mix(vec3(0.0, 0.2, 0.8), vec3(0.9, 0.1, 0.1), latitude);
  gl_FragColor = vec4(customColor, 1.0);
}

方案3:UV适配方案(必须使用UV时可选)

如果业务要求必须使用UV做渐变,可对极点区域做平滑过渡处理,消除尖峰:

void main () {
  // 定义极点过渡区域宽度
  float transitionWidth = 0.06;
  // 生成极点遮罩,上下顶点区域做平滑过渡
  float poleMask = smoothstep(0.0, transitionWidth, vUv.y) * (1.0 - smoothstep(1.0 - transitionWidth, 1.0, vUv.y));
  // 极点区域固定U值为0.5,避免跳变
  float smoothU = mix(0.5, abs(vUv.x * 2.0 - 1.0), poleMask);
  gl_FragColor = vec4(smoothU, vUv.y, 0.0, 1.0);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 18:27:02