第 5 章练习:smoothstep

对应教程:05 smoothstep 与平滑边缘
起始示例:硬边与软边,修改 05-smoothstep.js 和需要时的 05-smoothstep.html。

练习 1:仅反转柔和边界

**目标:**默认对照模式中,上半部分保持原样;下半部分改为左亮右暗,同时仍有柔和过渡。

**要求:**只修改 soft 的表达式,不交换 smoothstep 的两个 edge。

**完成标准:**拖动中心和羽化半宽时,下半部分的方向与上半部分相反,过渡宽度仍受滑块控制。

练习 2:让边缘宽度随高度变化

**目标:**新增一个模式,竖直分界线的底部较锐利、顶部较柔和。

**要求:**用 vUv.y 在 0.01~0.12 之间计算羽化半宽;横向中心仍由 uCenter 控制,给下拉框新增选项。

**完成标准:**同一条分界线从下往上逐渐变宽;移动中心滑块时,整条过渡线一起移动。

<details> <summary>提示</summary>

第 4 章的 mix(a, b, t) 可以用 vUv.y 在两个宽度间插值。

</details>

练习 3:判断边界条件

设 center = 0.5、feather = 0.1。下面的写法想得到左侧为 1、右侧为 0 的平滑遮罩:

float mask = smoothstep( center + feather, center - feather, vUv.x );

**目标:**说明问题所在并改写;给出修正后 vUv.x 分别为 0.4、0.5、0.6 时的结果。

**完成标准:**改写保持 edge0 < edge1,三个结果分别符合左亮、中间一半、右暗。

参考解答


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

第 5 章练习参考解答

对应练习:smoothstep。

练习 1:仅反转柔和边界

在 05-smoothstep.js 的片元着色器中:

float soft = 1.0 - smoothstep( uCenter - uFeather, uCenter + uFeather, vUv.x );

hard 不变。上半部分仍从左暗到右亮;下半部分从左亮到右暗。两个 edge 仍按从小到大排列。

练习 2:让边缘宽度随高度变化

在 05-smoothstep.html 增加:

<option value="3">上宽下窄的边缘</option>

在片元着色器中,把原来的模式判断整体替换为下面这段;颜色输出部分保持不变:

float mask;

if ( uMode == 0 ) {
  float hard = step( uCenter, vUv.x );
  float soft = smoothstep( uCenter - uFeather, uCenter + uFeather, vUv.x );
  mask = vUv.y >= 0.5 ? hard : soft;
} else if ( uMode == 3 ) {
  float variableFeather = mix( 0.01, 0.12, vUv.y );
  mask = smoothstep( uCenter - variableFeather, uCenter + variableFeather, vUv.x );
} else {
  float left = smoothstep(
    uCenter - 0.18 - uFeather,
    uCenter - 0.18 + uFeather,
    vUv.x
  );
  float right = 1.0 - smoothstep(
    uCenter + 0.18 - uFeather,
    uCenter + 0.18 + uFeather,
    vUv.x
  );
  float verticalBand = left * right;

  if ( uMode == 1 ) {
    mask = verticalBand;
  } else {
    float bottom = smoothstep( 0.32 - uFeather, 0.32 + uFeather, vUv.y );
    float top = 1.0 - smoothstep( 0.68 - uFeather, 0.68 + uFeather, vUv.y );
    mask = verticalBand * bottom * top;
  }
}

底部 vUv.y 接近 0,羽化半宽约 0.01;顶部接近 1,羽化半宽约 0.12。本题独立控制宽度,因此原来的羽化滑块在新模式中不起作用;其余模式仍使用它。如果接着完成了练习 1,可保留自己对 soft 的反向修改。

练习 3:判断边界条件

原代码使第一个 edge 为 0.6、第二个为 0.4,顺序倒置,GLSL 对此没有定义。正确写法是:

float mask = 1.0 - smoothstep( center - feather, center + feather, vUv.x );

结果如下:

vUv.x smoothstep(0.4, 0.6, x) mask
0.4 0.0 1.0
0.5 0.5 0.5
0.6 1.0 0.0