全部专题

SDF 描边为什么缩小后会闪?用 fwidth 保住边缘

距离场使用几何坐标单位,屏幕使用像素。缩放会改变一个距离单位占据的像素数,因此固定的 smoothstep 宽度会呈现不同的边缘厚度。fwidth 估算相邻片段间的数值变化,让过渡区维持约一个像素宽。

先固定问题

距离场用图形自身的单位描述远近,屏幕却用像素显示。缩放后,一个距离单位对应的像素数变化,所以固定的 smoothstep 宽度会忽粗忽细。fwidth 估计当前值跨越邻近片元的变化量,可以据此把过渡控制在约一个像素。

关键代码

float d=length(p)-radius;
float pixel=max(fwidth(d),0.00001);
float fill=1.0-smoothstep(-pixel,pixel,d);
float outline=1.0-smoothstep(pixel,2.0*pixel,abs(d));

按顺序验证

在等宽描边示例里拖动半径,先看固定阈值的一半,再看导数控制的一半。暂停后把过渡宽度依次乘 0.5 和 2,检查像素覆盖变化。

适用范围和常见错误

导数只在片段阶段使用。WebGL 1 要启用 OES_standard_derivatives;在非一致分支内部计算导数可能得到未定义结果,应在分支前计算。

继续实验

参考

官方文档

运行相关示例