GLSL 内置函数

smoothstep()

x 小于 edge0 时返回 0.0,大于 edge1 时返回 1.0,中间是一条平滑的 S 形曲线。

函数签名

float smoothstep(float edge0, float edge1, float x)
vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x)
vec2 smoothstep(float edge0, float edge1, vec2 x)
vec3 smoothstep(float edge0, float edge1, vec3 x)

参数

edge0
过渡开始的位置(结果为 0.0)。
edge1
过渡结束的位置(结果为 1.0),应大于 edge0。
x
要计算的值。

返回值

0.0 到 1.0 之间的值,计算方式为 t * t * (3.0 - 2.0 * t),其中 t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0)。

在线示例

修改右侧代码,左侧预览会实时更新。

工作原理

smoothstep(edge0, edge1, x) 是柔和版的 step。它不是从 0 突变到 1,而是缓入缓出:

  • x 小于等于 edge0:0.0
  • x 大于等于 edge1:1.0
  • 两者之间:一条平滑的 S 形曲线,两端慢、中间快

它内部先把 x 换算成从 edge0 到 edge1 走了百分之多少(0 到 1),再用 t * t * (3.0 - 2.0 * t) 把这条直线弯成 S 形。

示例画了一个圆,边缘是 smoothstep(0.6 - width, 0.6, d)。width 很小时边缘清晰但没有锯齿;width 很大时,圆就变成一团柔和的光晕。

常见用法

  • 抗锯齿图形:1.0 - smoothstep(r - 0.01, r, d) 得到边缘干净的圆。
  • 柔和遮罩和暗角:1.0 - smoothstep(0.2, 0.8, length(p)) 让四角变暗。
  • 动画缓动:smoothstep(0.0, 1.0, t) 让线性的 0 到 1 进度平缓地开始和结束。

常见错误

  • edge0 大于等于 edge1。GLSL ES 规范规定这种情况结果未定义。很多 GPU 会返回反向曲线,但想保证兼容,应写 1.0 - smoothstep(a, b, x),而不是 smoothstep(b, a, x)。
  • 过渡宽度无意中依赖了分辨率。uv 空间里 0.01 的宽度,在 300 像素的画布上约 3 像素,在 1000 像素的画布上就是 10 像素。

相关函数

用到 smoothstep() 的教程