第 21 章练习:SDF 视觉效果

对应教程:21 SDF 的视觉效果
起始示例:带孔徽牌的距离效果,需要修改时使用示例源码。

练习 1:估算发光衰减

假设点位于徽牌外部,fill≈0,uGlow=0.08,暂时只看示例的指数因子 exp(-d/uGlow)。

**目标:**算出 d=0、0.08、0.16 时的因子;指出增大 uGlow 后同一外部距离处的光晕会怎样变化。

**完成标准:**能说明 uGlow 是指数衰减距离,不是光晕的硬截止半径;知道最终亮度还受颜色与 0.65 强度系数影响。

练习 2:把对称描边改成仅内侧描边

**目标:**新增一个“仅内侧描边”模式。让 uOutline 表示从零边界向形状内部延伸的宽度;外轮廓和圆孔边缘都应有内侧金线。

**要求:**在现有末尾描边分支中增加模式,保留组合预览与原“仅描边”模式的对称线;两条描边边缘都使用已有的 aa 进行抗锯齿。

**完成标准:**金线只覆盖 -uOutline < d < 0 附近,圆孔的外部不会出现另一半描边;改变宽度控件时,金线主要向徽牌实体内侧变宽。

练习 3:比较“带孔阴影”与“实心阴影”

**目标:**在“填充与柔和阴影”模式中,把阴影所用的距离场临时改为外侧圆角矩形,不从阴影里挖圆孔;徽牌本体仍有孔。比较孔附近的颜色。

**要求:**只修改阴影的查询函数,保持本体 d=sdBadge(p)、偏移、软边和合成顺序不变。完成后恢复原式。

**完成标准:**实心阴影会更明显地透过徽牌的圆孔显示;能解释为什么阴影形状与本体形状可以由不同距离场决定,而这仍是二维遮罩效果。

参考解答


<a id=“reference-answers”></a>

第 21 章练习参考解答

对应练习:SDF 视觉效果。

练习 1:估算发光衰减

外部距离 d exp(-d/0.08)
0 1
0.08 e⁻¹≈0.368
0.16 e⁻²≈0.135

实际 shader 还乘 (1-fill)、发光颜色和 0.65,所以边界附近像素的最终颜色不直接等于表中数值。增大 uGlow 会让同一正距离处的指数下降得更慢,光晕扩散更远;它没有某个自动变为零的半径。

练习 2:把对称描边改成仅内侧描边

在 HTML 的 #mode 下拉框追加 <option value="6">仅内侧描边</option>。把片元 shader 最后的描边 if 整块替换为:

// 片元阶段;d、uOutline、aa 均为平面高度单位。
if ( uMode == 0 || uMode == 2 || uMode == 6 ) {
  float outline;
  if ( uMode == 6 ) {
    float afterInnerEdge = smoothstep( -uOutline - aa,
                                       -uOutline + aa, d );
    float beforeOuterEdge = 1.0 - smoothstep( -aa, aa, d );
    outline = afterInnerEdge * beforeOuterEdge;
  } else {
    outline = 1.0 - smoothstep( -aa, aa,
                                abs( d ) - 0.5 * uOutline );
  }
  color = mix( color, vec3( 1.0, 0.70, 0.23 ), outline );
}

模式 6 不满足前面的填充、发光和阴影条件,因此只在背景上画内侧金线。afterInnerEdge 在 d=-uOutline 附近从 0 变 1,beforeOuterEdge 在 d=0 附近从 1 变 0;乘积只留下内侧带。模式 0 和 2 继续使用原对称描边。圆孔周围的 d<0 区域位于徽牌实体内,所以金线会落在孔外侧的实体上。

练习 3:比较“带孔阴影”与“实心阴影”

只替换阴影分支内计算 shadowD 的一行:

// 片元阶段;仍从 p 减去偏移,仅阴影使用外轮廓场。
float shadowD = sdRoundBox( p - uShadowOffset,
                            vec2( 0.50, 0.28 ), 0.09 );

保留紧接其后的 shadowAa、shadow、颜色混合,以及前面 d=sdBadge(p) 的本体计算。阴影现在是一块实心圆角矩形,本体依然有圆孔,因而孔内可能透出更多暗色阴影。恢复 float shadowD=sdBadge(p-uShadowOffset); 后,阴影自己也有孔,孔附近的暗色分布随偏移而改变。这是为两层二维遮罩选择不同形状;没有新增真实投影几何。