第 4 章练习:阈值与遮罩
对应教程:04 数值映射与阈值
起始示例:阈值与遮罩,修改 04-threshold.js 和需要时的 04-threshold.html。
每道题都从起始示例开始;也可以保留上一题的改动,依次增加新模式。先观察默认效果,再修改代码。
练习 1:反向分界
**目标:**在默认的左右分界模式中,让阈值左侧为亮色、右侧为暗色。
**要求:**只修改 uMode == 0 分支中的遮罩表达式,不交换 darkColor 与 lightColor。
**完成标准:**拖动阈值时,亮色区域从左向右扩大或缩小,边界仍是硬边。
<details> <summary>提示</summary>
原遮罩只有 0 和 1;考虑如何把 0 变成 1、把 1 变成 0。
</details>
练习 2:画一个空心矩形框
**目标:**新增一个模式,在 UV 的 0.2~0.8 正方形区域画出一个框,并挖去中央 0.35~0.65 的正方形。
**要求:**用 step 构造内外两个 0/1 矩形遮罩,再相减;给下拉框新增选项。框外和中央都应为暗色。
**完成标准:**新模式显示四边亮、中间暗的封闭方框;原模式不变。
<details> <summary>提示</summary>
可以分别求 x、y 方向的带,再用 min 求交集。外矩形减去内矩形。
</details>
练习 3:由半宽控制线性过渡
**目标:**新增一个颜色渐变模式,以 uThreshold 为中心,过渡从 uThreshold - uHalfWidth 开始,到 uThreshold + uHalfWidth 结束。
**要求:**用 clamp 和 mix,使“条带半宽”滑块同时成为过渡的半宽控制。不要使用下一章的 smoothstep。
**完成标准:**改变阈值只移动过渡区;增大半宽使过渡更宽;阈值处恰好是两色的中间值。
<a id=“reference-answers”></a>
第 4 章练习参考解答
对应练习:阈值与遮罩。改动基于第 4 章示例。
练习 1:反向分界
把默认分支改为:
if ( uMode == 0 ) {
mask = 1.0 - step( uThreshold, vUv.x );
}
原本左侧为 0、右侧为 1;减去后正好反过来。mix(darkColor, lightColor, mask) 的颜色顺序没有改变。
练习 2:画一个空心矩形框
在 04-threshold.html 的下拉框中增加:
<option value="5">空心矩形框</option>
在片元着色器原有 uMode == 3 分支后,保留旧的过渡模式为 uMode == 4,再增加新分支:
} else if ( uMode == 4 ) {
mask = clamp( ( vUv.x - uThreshold ) * 4.0 + 0.5, 0.0, 1.0 );
} else if ( uMode == 5 ) {
float outerX = step( 0.2, vUv.x ) - step( 0.8, vUv.x );
float outerY = step( 0.2, vUv.y ) - step( 0.8, vUv.y );
float innerX = step( 0.35, vUv.x ) - step( 0.65, vUv.x );
float innerY = step( 0.35, vUv.y ) - step( 0.65, vUv.y );
float outerMask = min( outerX, outerY );
float innerMask = min( innerX, innerY );
mask = outerMask - innerMask;
}
内矩形完全在外矩形内,因而相减不会得到负值。框内部为 1 - 0 = 1,中央为 1 - 1 = 0,框外为 0 - 0 = 0。这个方案的边界是硬边。
练习 3:由半宽控制线性过渡
继续在下拉框增加:
<option value="6">可调宽度的线性过渡</option>
接在上一题的 uMode == 5 分支后:
} else if ( uMode == 6 ) {
float start = uThreshold - uHalfWidth;
mask = clamp( ( vUv.x - start ) / ( 2.0 * uHalfWidth ), 0.0, 1.0 );
}
滑块的最小半宽为 0.02,分母始终大于 0。vUv.x == start 时结果为 0;到 uThreshold + uHalfWidth 时为 1;恰在 uThreshold 时为 0.5。示例末尾已有的 mix(darkColor, lightColor, mask) 完成颜色混合。如果独立完成本题,模式编号和分支位置可以不同,只需保证原模式仍可用。