SDF 矩形
11 / 18
练习着色器中常用的数学基础积木。
矩形的有符号距离函数(SDF)用一行代码计算每个像素到矩形边界的距离:
下面拆解它。
什么是 SDF
SDF(Signed Distance Field,有符号距离场)给每个像素一个距离值:
- 负值:在形状内部
- 0:正好在边界上
- 正值:在形状外部
知道了距离,用一个 smoothstep 就能画出带柔软边缘的形状,不需要复杂的光栅化判断。
sdBox 的逻辑
p 是像素相对于矩形中心的位置,b 是矩形的半宽/半高(比如 vec2(0.2, 0.12) 表示宽 0.4、高 0.24 的矩形)。
abs(p) - b 利用对称性只看第一象限:
- 结果为负 → 当前像素的 x 或 y 分量在矩形范围内
- 结果为正 → 超出矩形范围
length(max(d, 0.0)) 计算外部角落区域的距离(让角落是圆润还是尖锐取决于后续);min(max(d.x, d.y), 0.0) 计算内部和外侧边的贡献,两者相加得到完整的 SDF 值。
用 smoothstep 把距离变成遮罩
- d < 0(内部)→ smoothstep 输出 0 → 遮罩为 1(白色)
- d > 0.01(外部)→ smoothstep 输出 1 → 遮罩为 0(黑色)
- 0 到 0.01 之间 → 柔和过渡
0.01 是边缘柔化的宽度,值越小边缘越硬。
试着改一改
| 改动 | 效果 |
|---|---|
把 vec2(0.2, 0.12) 改成 vec2(0.3, 0.3) | 正方形 |
把 vec2(0.2, 0.12) 改成 vec2(0.4, 0.05) | 细长横条 |
把 0.01 改成 0.05 | 边缘更模糊 |
把 1.0 - smoothstep(0.0, 0.01, d) 改成 1.0 - smoothstep(-0.01, 0.01, d) | 边缘更宽的柔化 |
练习
调用 sdBox(p, vec2(0.2, 0.12)) 计算距离 d,让画面显示一个白色矩形。
答案解析
p = vUv - 0.5 把坐标原点移到屏幕中心,sdBox 计算每个像素到以中心为原点、半宽 0.2、半高 0.12 的矩形的有符号距离。1.0 - smoothstep(0.0, 0.01, d) 把负值(内部)转为 1(白色),把正值(外部)转为 0(黑色),边界处有 0.01 宽的柔化过渡。
练习起始 float d = 0.0,整个画面都处于"恰好在边界"的状态,遮罩计算会显示一片均匀的值。把它换成正确的 sdBox 调用就能看到矩形。
试着把 vec2(0.2, 0.12) 改成 vec2(0.1, 0.25),看看竖条形状。