跳到主要内容
3D Playground
WebGL 与着色器第 6 / 12 节

片元着色器艺术:SDF 与调色板

进阶WebGL 2

全屏三角形

只要一个盖住整个屏幕的三角形(3 个顶点、无需缓冲区),每个像素就都会跑一次片元着色器。从此画面完全由一个“像素 → 颜色”的函数决定,这正是 Shadertoy 的玩法。

坐标:uv 与 p

  • uv = gl_FragCoord.xy / iResolution:0 到 1,适合做渐变。
  • p = (2.0 * gl_FragCoord.xy - iResolution) / iResolution.y:中心为原点、y 从 -1 到 1,并按高度归一化,保证圆是圆的。

有向距离场(SDF)

SDF 返回点到形状边界的有符号距离:内部为负、边上为 0、外部为正。

glsl
float sdCircle(vec2 p, float r) { return length(p) - r; }
float sdBox(vec2 p, vec2 b, float r) {
  vec2 q = abs(p) - b + r;
  return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - r;
}

组合非常简单:并集取 min(a, b),交集取 max(a, b),差集取 max(a, -b)。平移就是把 p 减去位置,旋转就是乘一个 2×2 矩阵。打开“show distance field”,能直接看到距离的等值线。

smoothstep 抗锯齿

用 d < 0.0 判断内外会得到锯齿边。改成在边界附近约一个像素宽的范围内做平滑过渡:

glsl
float px = 2.0 / iResolution.y;          // 一个像素在 p 空间的大小
float fill = 1.0 - smoothstep(-px, px, d);

把“smoothstep width”调大,硬边就会变成柔和的发光;调到 0,就能看到锯齿回来了。距离本身还能做光晕:exp(-k * d) 随距离衰减。

余弦调色板

Inigo Quilez 的公式只用四个 vec3 参数就能生成无数配色:

glsl
vec3 palette(float t) { return a + b * cos(6.2831853 * (c * t + d)); }

把形状编号、时间、到中心的距离组合成 t,颜色就会随位置和时间流动。面板里切换三套预设,看看只改 d 能带来多大变化。

核心 API

gl_FragCoordgl_VertexIDsmoothsteplengthmin / maxmixcos

动手试试

  1. 1用 max(a, -b) 从中心方块里挖掉一个圆。
  2. 2给 palette 写第四套预设,比如 d = vec3(0.3, 0.2, 0.2)。
  3. 3让圆的数量随时间变化,或让方块随鼠标旋转。
运行中