第 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 |