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

如何在GL ES中让片元着色器生成的星芒渐变从黑色改为透明过渡

问题根源

  1. 片元着色器输出的alpha值固定为1.0,光晕边缘亮度较低的区域会输出深灰色甚至纯黑的不透明像素,多颗星叠加时深色边缘就会形成明显的黑边
  2. 未针对发光星点配置正确的混合模式,自发光物体叠加应该使用加性混合逻辑,避免变暗
  3. 硬discard低于阈值的像素会导致边缘出现锯齿,无法实现自然的透明度过渡

修复方案

1. 修改片元着色器

重新计算alpha通道,修复中心除零异常,实现边缘自然透明衰减:

varying vec3 vGlow;

void main() {
  float starLuminosity  = 250.0;
  float invRadius = 60.0;
  float invGlowRadius = 2.5;
  float alphaCutoff = 0.01;

  // 计算相对于点中心的坐标
  vec2 position = gl_PointCoord - 0.5;
  float dist = length(position);
  // 加极小值避免中心距离为0时出现除零错误
  float diskScale = dist * invRadius + 1e-6;

  // 艾里斑计算
  vec3 glow = vGlow / pow(diskScale, invGlowRadius);
  glow *= starLuminosity;

  // 取RGB最大值作为透明度基准,也可替换为灰度计算适配不同星点颜色
  float alpha = max(max(glow.r, glow.g), glow.b);
  // 平滑过渡边缘,避免硬切
  alpha = smoothstep(alphaCutoff, 0.1, alpha);

  // 可选:丢弃透明度极低的像素,优化渲染性能
  if (alpha < alphaCutoff) {
    discard;
  }

  gl_FragColor = vec4(glow, alpha);
}

2. 调整Three.js材质配置

开启透明和加性混合,关闭深度写入避免透明区域遮挡错误:

const starMaterial = new THREE.ShaderMaterial({
  vertexShader: 你的顶点着色器代码,
  fragmentShader: 修改后的片元着色器代码,
  transparent: true,
  // 加性混合适配发光效果,叠加时只会提升亮度不会出现暗边
  blending: THREE.AdditiveBlending,
  // 关闭深度写入,避免近处星点的透明区域遮挡远处星点
  depthWrite: false,
  // 保留深度测试保证星点会被行星等不透明天体遮挡
  depthTest: true
});

如果效果不符合预期,可以调整starLuminosity、invGlowRadius的数值控制光晕亮度和衰减速度,也可以调整smoothstep的两个阈值参数调整边缘过渡的软硬程度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 17:54:00