塑形函数:在 0 到 1 之间掰弯一条线
Shaping Functions
先从一条直线开始
片元着色器对屏幕上的每个像素运行一次,输入是这个像素的位置,输出是它的颜色。把位置除以画布尺寸,就得到 0 到 1 之间的归一化坐标 st。
最简单的一件事:把 st.x 直接当作亮度。左边是 0(黑),右边是 1(白),中间是一条均匀的渐变。如果再把 y = x 这条线画在上面,你会看到一条从左下到右上的对角线。
《着色器之书》把这一步比作宫城先生的「篱笆课」:在继续把二维坐标映射到四维颜色之前,先得把一维练熟——在 0 到 1 这个小区间里,学会把一条线随心所欲地掰弯。
也可以直接改右边的代码:停手约 0.3 秒会自动重新运行;改坏了点「还原代码」。
x 和 y(或亮度)一一对应,这就是线性插值。接下来要做的,是用数学函数把这条线弯过来。
幂:给数据流「针灸」
把 x 升到 5 次方,直线会变成一条贴着底部、最后才猛然抬头的曲线;指数小于 1 时正好反过来,一开始就冲上去。
拖动下面的滑块改指数,依次试试书里建议的 20、2、1、0、0.2、0.02,体会「值」和「指数」的关系:
直接改上面的表达式就能重画:x 是 0 到 1 的横坐标,可以用 sin、pow、smoothstep 等函数。
pow 是 GLSL 的内建函数,和 exp、log、sqrt 一样大多有硬件加速——用对了地方,它们比自己手写的级数更快。
step 与 smoothstep:硬开关和软开关
这两个是 GLSL 里特别常用的插值函数。
step(edge, x):x小于阈值时返回 0,否则返回 1。一刀切。smoothstep(edge0, edge1, x):在[edge0, edge1]之间做平滑过渡,两端的斜率都是 0,所以接缝处看不出折角。
两个 smoothstep 相减 = 一个凸起
前面「篱笆」里画线用的 plot() 正是这个技巧:让一个 smoothstep 早一点升起,另一个晚一点升起,两者相减,中间就剩下一个窄窄的凸起。
在下面的绘图器里点一点预设,或者直接改表达式:
直接改上面的表达式就能重画:x 是 0 到 1 的横坐标,可以用 sin、pow、smoothstep 等函数。
正弦与余弦:会动的曲线
给定一个弧度角,cos 和 sin 分别给出单位圆上那一点的 x 和 y。它们的值在 −1 和 1 之间平滑往返,天生适合做动画。书里给了一串练习,每一个都值得亲手试一下:
直接改上面的表达式就能重画:x 是 0 到 1 的横坐标,可以用 sin、pow、smoothstep 等函数。
再把 mod、clamp、min、max、sign 这些函数组合进来,就是生成艺术里常见的一维「调料架」。
在游戏里怎么用
塑形函数在游戏里随处可见,只是平时它们叫别的名字。
下面这个例子把同一段运动交给四条不同的曲线:从上到下依次是线性、smoothstep、pow(t, 3.0),以及用 abs(cos) 做出的回弹。看看哪一个最「顺手」。
也可以直接改右边的代码:停手约 0.3 秒会自动重新运行;改坏了点「还原代码」。
取舍与常见的坑
小结与练习
- 在 [0,1] 这一小段里,
pow控制快慢,step/smoothstep控制开关,sin/cos带来周期和动画; - 两个 smoothstep 相减能画出一条细线或一片亮带,这是后面画形状的基础;
- 缓动、溶解边、呼吸灯——游戏里很多「手感」其实就是一条塑形曲线。
练习:找一份 Kynd 的方程表,挑几条用上面的绘图器复刻出来,留意它们是怎么把函数组合起来、把值控制在 0 到 1 之间的。工具箱里可以收藏 LYGIA 的数学分区,以及 Íñigo Quilez 做的 GraphToy。
塑形函数把归一化到 的一维输入弯成可控制的曲线,是片元着色器里混合颜色、画边、做动画缓动的「基本功」。GLSL 的 pow/step/smoothstep/sin 等多为硬件加速;掌握一维再扩展到二维空间。
为什么先练一维(「篱笆课」)
《着色器之书》把本章比作宫城先生的篱笆课:之前把归一化的 、 映到红绿通道,本质是 。在继续升维变换前,必须先精通 一维函数——在 区间里塑造一条线。
典型练习结构(「篱笆」):
- 用亮度显示
st.x(黑到白的梯度); - 再在上方用绿线画出 (
plot用双smoothstep做竖切凸起)。
vec3(v) 会把三个颜色通道都设为 ;vec4(vec3, a) 用三维颜色加 alpha。一维上 与 (或亮度)的一一对应就是线性插值;从此用数学函数把线掰弯。
幂、指数与其它原生函数
例如把 升到 5 次方得到曲线。换指数(20、2、1、0、0.2、0.02)能体会「值—指数」关系——书中称为对数据流的「针灸式」控制。
pow 是 GLSL 原生且常硬件加速;还可换 exp、log、sqrt。与 组合时常更有趣(可用宏 #define PI 3.14159265359)。
step 与 smoothstep
二者是 GLSL 特有的硬件加速插值:
step(edge, x):小于阈值返回0.0,否则1.0——硬开关。smoothstep(edge0, edge1, x):在[edge0, edge1]上对 做平滑插值(Hermite)。
画线的 plot 把两个 smoothstep 相减,在某一 处形成凸起:
smoothstep(0.2,0.5,st.x) - smoothstep(0.5,0.8,st.x) 看起来像竖直切片上的亮带。
正弦、余弦与组合拳
给定弧度角,单位圆上 、,返回值在 且光滑,极适合动画与塑形。练习包括:
- 在
sin前给 加u_time(波形沿 运动); - 乘 使每 2 个整数一个周期;
- 用
u_time * x压缩相位频率; sin(x)+1抬到 ;sin(x)*2加倍振幅;abs(sin(x))像弹跳轨迹;fract(sin(x))取小数;ceil+floor得到 数字波。
再与 mod、clamp、min/max、sign 等组合,就是生成艺术里常见的一维「调料架」。
进阶资源(书中指向)
- Golan Levin:多项式 / 指数 / 圆与椭圆 / 贝塞尔等塑形函数文档,宜移植到 GLSL。
- Íñigo Quilez:常用函数文集;移植时注意浮点小数点与 C 名差异(如
pow而非powf)。 - Kynd 的方程表:练习在 内组合函数性质。
- 工具箱:LYGIA 的 math 分区;Quilez 的 GraphToy。
在游戏开发中的意义
- UI 与镜头:缓动 (easing) 本质是塑形函数(Robert Penner 族可作参考,但自制过渡往往更好)。
- 材质与 VFX:边缘柔化、光带、呼吸动画几乎都是
smoothstep/sin组合。 - 性能:优先用原生硬件函数,避免在片元里写昂贵级数除非必要。
原书问题
- ch.05「Advance shaping functions」将 Íñigo Quilez 写作「Iñigo Quiles」(缺 z、重音不一致);正文链接指向 iquilezles.org,本页按正确拼写引用。