第 6 章练习:取整与重复图案
对应教程:06
floor、ceil、fract与重复图案
起始示例:UV 重复与取整,修改 06-repeat.js 和需要时的 06-repeat.html。
练习 1:手算单元编号和局部位置
设 uRepeat = 4.0,某片元 vUv = vec2(0.37, 0.62)。
**目标:**分别计算 grid、cell = floor(grid)、localUv = fract(grid)。再计算单个数值 -0.2 的 floor、ceil 和 fract。
**完成标准:**能说明哪个结果用于识别单元,哪个结果用于在单元内部画图案,并正确处理负数。
练习 2:棋盘格改成横条
**目标:**让同一行的所有单元颜色相同,相邻行交替变色。
**要求:**只修改棋盘格模式中 parity 的表达式,不改动颜色和 mix。
**完成标准:**改变重复次数后,横向仍不交替,纵向依次交替。
练习 3:每个单元画一个小方块
**目标:**新增模式:每个重复单元的中央 0.25~0.75 区域为亮色,其余为暗色。
**要求:**使用 localUv,而非原始 vUv,用第 4 章的 step 组合方形遮罩;新增一个模式选项。
**完成标准:**每个单元都有相同位置、相同大小的亮色方块;改变重复次数只改变方块数量。
<details> <summary>提示</summary>
先对 localUv.x 求一条宽为 0.5 的带,再对 localUv.y 做同样的事。
</details>
练习 4:隔行错位的棋盘格
**目标:**新增模式:仍然让单元交替着色,但每隔一行把竖向单元边界水平错开半个单元。
**要求:**先从原始 cell.y 求行奇偶,再在计算该行的列号前偏移 grid.x。
**完成标准:**偶数行边界与原棋盘格相同;奇数行的竖向边界相对移动半个单元,颜色仍交替。
<a id=“reference-answers”></a>
第 6 章练习参考解答
对应练习:取整与重复图案。
练习 1:手算单元编号和局部位置
grid = (0.37, 0.62) * 4.0 = (1.48, 2.48)
cell = floor(grid) = (1.0, 2.0)
localUv = fract(grid) = (0.48, 0.48)
floor(-0.2) = -1.0
ceil(-0.2) = 0.0
fract(-0.2) = 0.8
cell 是从 0 开始的单元编号,localUv 是当前单元内的位置。负数的 floor 向更小的整数走,所以不是 0。
练习 2:棋盘格改成横条
棋盘格分支中的行改为:
float parity = mod( cell.y, 2.0 );
不再使用 cell.x,横向所有单元保持同色;每往上一行,cell.y 加 1,颜色翻转。
练习 3:每个单元画一个小方块
在 06-repeat.html 的下拉框中增加:
<option value="4">每格一个方块</option>
保留原有的 uMode == 0、1、2 分支,把最后的 else 改成 else if (uMode == 3),然后增加:
} else if ( uMode == 4 ) {
float bandX = step( 0.25, localUv.x ) - step( 0.75, localUv.x );
float bandY = step( 0.25, localUv.y ) - step( 0.75, localUv.y );
float square = min( bandX, bandY );
color = mix( vec3( 0.04, 0.14, 0.28 ), vec3( 0.9, 0.7, 0.35 ), square );
}
关键是从每个单元重新归零的 localUv 上取阈值。若用 vUv,只会在整个平面上画一个方块。
练习 4:隔行错位的棋盘格
再给下拉框增加:
<option value="5">错位棋盘格</option>
接在上一题新分支后:
} else if ( uMode == 5 ) {
float oddRow = mod( cell.y, 2.0 );
float shiftedColumn = floor( grid.x + 0.5 * oddRow );
float parity = mod( shiftedColumn + cell.y, 2.0 );
color = mix( vec3( 0.04, 0.14, 0.28 ), vec3( 0.9, 0.7, 0.35 ), parity );
}
偶数行 oddRow = 0.0,列号仍是 floor(grid.x);奇数行先偏移 grid.x 半个单元,再求列号,于是边界错开。单元右端的 vUv == 1.0 正好落在边界上,最外缘一条像素可能呈现下一单元的颜色;这不影响内部规律。