程序化图案:画一格,铺满一墙
Procedural Patterns
为什么着色器擅长重复
片元着色器对每个像素只算一次。一块画布上画 1 个圆还是 100 个圆,每个像素要做的计算几乎一样多。所以重复的图案特别适合交给着色器:重复的次数几乎不影响开销。
《10 PRINT》这本书里说,网格给人的直觉和创造提供了一个框架,也留下了打破它的余地;在混沌的自然里,图案许诺了一种秩序。从陶器上的纹样到罗马浴场的马赛克,人们一直在用网格装饰生活。
fract:把空间切成格子
fract(x) 返回 x 的小数部分,相当于 mod(x, 1.0)。st 本来就在 0 到 1 之间,直接取 fract 什么也不会发生。但如果先把 st 乘以 3,坐标就会从 0 走到 3,再取 fract,就得到三段从 0 到 1 的重复。
每一格里的坐标都是一个缩小版的 st,所以前几课画形状的代码可以原封不动地搬进来:
也可以直接改右边的代码:停手约 0.3 秒会自动重新运行;改坏了点「还原代码」。
floor:知道自己在第几格
fract 告诉你「在格子里的哪里」,floor 告诉你「在第几格」。两者是一对:st * 3.0 = floor(st * 3.0) + fract(st * 3.0)。
有了格子的编号,就能让不同的格子画不同的东西。书里的练习是画一盘井字棋:
也可以直接改右边的代码:停手约 0.3 秒会自动重新运行;改坏了点「还原代码」。
在每一格里变换坐标
每一格都是一个小小的坐标系,上一课的平移、旋转、缩放可以直接用在格子里。先用 fract(st) - 0.5 把每格的原点挪到格子中心,再乘旋转矩阵,格子里的形状就会原地自转。再配合棋盘格的编号,让相邻的格子朝相反的方向转:
也可以直接改右边的代码:停手约 0.3 秒会自动重新运行;改坏了点「还原代码」。
错位:砌一面砖墙
看一面砖墙:每隔一行,砖就往旁边错开半块。要做到这一点,先得知道当前像素在奇数行还是偶数行:对行号取 mod(row, 2.0),结果不是 0 就是 1。
判断奇偶可以写三元运算 mod(row, 2.0) < 1.0 ? 0.0 : 1.0,也可以写 step(1.0, mod(row, 2.0))。书里推荐后者:虽然很难知道每块显卡具体怎么编译优化,但可以放心假设内建函数比自己写的逻辑更快。能用内建函数时就用。
也可以直接改右边的代码:停手约 0.3 秒会自动重新运行;改坏了点「还原代码」。
Truchet:一块砖,四个朝向
知道了格子的位置,就能让同一个元素按位置摆出不同的朝向。Truchet 砖就是这个思路:一块被对角线切开的方砖,转 0°、90°、180°、270° 就有四种摆法。按一定规则把它们拼在一起,能组合出无穷多种复杂的图案。
下面的例子把每个格子再切成 2 × 2 个小格,按小格的位置决定转几次 90°。拖动「样式」滑块,把三角换成两段四分之一圆弧,图案会变成一条条连贯的曲线:
也可以直接改右边的代码:停手约 0.3 秒会自动重新运行;改坏了点「还原代码」。
在游戏里怎么用
取舍与常见的坑
小结与练习
fract(st * n)把画布切成 n × n 个格子,每一格都是一个新的 0~1 坐标系;floor(st * n)给出格子的编号。- 在格子里可以照常画形状,也可以平移、旋转、缩放;按编号的奇偶可以做错位和棋盘格。
- Truchet 砖用同一个元素的不同朝向拼出复杂的图案。
练习:设计一块自己的地砖:用这几课学到的形状画一个最小单元,然后用格子编号决定它的颜色和朝向,铺满整个画布。
片元着色器按像素执行:形状重复多少次,计算量几乎不变,因此特别适合平铺图案。核心手法是放大 st 再 fract 得到重复的 子空间,再在格子内画形、做矩阵变换,或按奇偶行错位、按格子旋转拼 Truchet。
为何适合平铺
引用 10 PRINT:网格给人直觉与发明的框架,也可被颠覆;图案在自然混沌中承诺秩序。算法上:fract(x) 取小数部分,等价于 mod(x,1.0)。st 已在 时单独 fract 无意义;若先把空间 ×3,则出现三段 线性重复,可在每个子空间画同一形状。xy 不等倍乘可改长宽比。
练习:封装 tiling 函数;3×3 网格识别行列做井字棋;格子内再做平移/旋转/缩放动画;多层图案拼苏格兰格子。
错位图案(砖墙)
隔行半砖错位:用 mod(row, 2.0) 判断奇偶(<1 为偶行语义视实现),奇数行给 x 加 0.5 偏移。step 常比手写三元更快(内建更易被优化)。可拉长格子模拟现代砖比例;动画可使偶行与奇行反向滑动,或行列同时错位。
Truchet 砖
同一设计元素可有四种朝向;按格子位置选择旋转,能拼出无穷复杂图案。rotateTilePattern() 把空间分成四格并赋不同转角。可把黑白三角换成半圆、旋转方、线段;或按位置改其它属性;甚至非装饰用途(如易经卦象示例)。
方法论
程序化图案是在找最小可复用单元,在可预期的秩序与意外的变化之间走钢丝——希腊回纹、中国窗格、阿拉伯几何、非洲织物皆同理。本章结束「算法绘图」;下一章引入熵做生成设计。