本文最后更新于:2025年4月17日 晚上
线性插值函数
l e r p ( y 1 , y 2 , w e i g h t ) = y 1 + ( y 2 − y 1 ) × w e i g h t lerp(y_1, y_2, weight) = y_1 + (y_2 - y_1) \times weight
l er p ( y 1 , y 2 , w e i g h t ) = y 1 + ( y 2 − y 1 ) × w e i g h t
其中 w e i g h t weight w e i g h t 是一个在 [0, 1] 区间的实数,倒不是因为取更大的值后这个函数就无定义了,而是因为取了更大的值,这个函数就失去了我们构造它的理由,另外,CG 会限制 w e i g h t weight w e i g h t 的值在 [0, 1] 的范围内,超过这个范围会被留在边界 0 或者边界 1。
这里 y 1 y_1 y 1 被称为起点,而 y 2 y_2 y 2 被称为终点,lerp 函数就是取值 y 1 y_1 y 1 到 y 2 y_2 y 2 中间的一个值。取值由 w e i g h t weight w e i g h t 来控制,当 w e i g h t weight w e i g h t 为 0.5 时,取值刚好在起点和终点之间。为了更加方便理解,可以把公式写成这种形式:
l e r p ( y 1 , y 2 , w e i g h t ) = ( 1 − w e i g h t ) × y 1 + w e i g h t × y 2 lerp(y_1, y_2, weight) = (1 - weight) \times y_1 + weight \times y_2
l er p ( y 1 , y 2 , w e i g h t ) = ( 1 − w e i g h t ) × y 1 + w e i g h t × y 2
简单来说,lerp 函数是在 y 1 y_1 y 1 和 y 2 y_2 y 2 之间过渡。y 1 y_1 y 1 和 y 2 y_2 y 2 可以是一个值,也可以是一个函数。比如,我们可以在正弦函数和线性函数之间做过渡,我们先看一下正弦函数:
再看一下最简单的线性函数 y = x y = x y = x
在它俩之间过渡,我们只需要使用 l e r p ( sin x , x , 0.5 ) lerp(\sin x, x, 0.5) l er p ( sin x , x , 0.5 ) 即可。当然可以调整 w e i g h t weight w e i g h t 参数观察不同的结果。
当 y 1 y_1 y 1 和 y 2 y_2 y 2 分别为两个点时,结果就是两点间的位置。
贝塞尔曲线
当有 A A A 、B B B 、C C C 三个点且有 D D D 为从 A A A 到 C C C 上权重为 t t t 的插值,E E E 为从 C C C 到 B B B 上权重为 t t t 的插值,点 F F F 为从 D D D 到 E E E 上权重为 t t t 的插值,则点 F F F 是以 A A A 为起点、B B B 为终点、C C C 为控制点的二阶贝塞尔曲线上的一点。
同理,当有 A A A 、B B B 、C C C 、D D D 四个点,E E E 为从 A A A 到 C C C 上权重为 t t t 的插值,F F F 为从 C C C 到 D D D 上权重为 t t t 的插值,G G G 为从 D D D 到 B B B 上权重为 t t t 的插值,且 H H H 为从 E E E 到 F F F 上权重为 t t t 的插值,I I I 为从 F F F 到 G G G 上权重为 t t t 的插值,J J J 为从 H H H 到 I I I 上权重为 t t t 的插值,则点 J J J 是以 A A A 为起点、B B B 为终点、C C C 和 D D D 为控制点的三阶贝塞尔曲线上的一点。
二阶贝塞尔曲线公式推导
由 f ( p 0 , p 1 , t ) = ( p 1 − p 0 ) × t + p 0 f(p_0, p_1, t) = (p_1 - p_0) \times t + p_0 f ( p 0 , p 1 , t ) = ( p 1 − p 0 ) × t + p 0 可得:
D = ( C − A ) t + A E = ( B − C ) t + C F = ( E − D ) t + D = ( ( ( B − C ) t + C ) − ( ( C − A ) t + A ) t + ( ( C − A ) t + A ) ) = ( A t + B t − 2 C t + C − A ) t + C t − A t + A = ( t − 1 ) 2 A + t 2 B + 2 t ( 1 − t ) C B ( t ) = ( 1 − t ) 2 A + t 2 B + 2 t ( 1 − t ) C , t ∈ [ 0 , 1 ] \begin{aligned}
D &= (C - A)t + A\\
E &= (B - C)t + C\\
F &= (E - D)t + D\\
&= (((B - C)t + C) - ((C - A)t + A)t + ((C - A)t + A))\\
&= (At + Bt -2Ct + C - A)t + Ct - At + A\\
&= (t - 1)^2A + t^2B + 2t(1 - t)C\\
\\
B(t) &= (1 - t)^2A + t^2B + 2t(1 - t)C, t \in [0, 1]
\end{aligned}
D E F B ( t ) = ( C − A ) t + A = ( B − C ) t + C = ( E − D ) t + D = ((( B − C ) t + C ) − (( C − A ) t + A ) t + (( C − A ) t + A )) = ( A t + Bt − 2 Ct + C − A ) t + Ct − A t + A = ( t − 1 ) 2 A + t 2 B + 2 t ( 1 − t ) C = ( 1 − t ) 2 A + t 2 B + 2 t ( 1 − t ) C , t ∈ [ 0 , 1 ]
三阶贝塞尔曲线公式推导
由 f ( p 0 , p 1 , t ) = ( p 1 − p 0 ) × t + p 0 f(p_0, p_1, t) = (p_1 - p_0) \times t + p_0 f ( p 0 , p 1 , t ) = ( p 1 − p 0 ) × t + p 0 可得:
E = ( C − A ) t + A F = ( D − C ) t + C G = ( B − D ) t + D \begin{aligned}
E &= (C - A)t + A\\
F &= (D - C)t + C\\
G &= (B - D)t + D\\
\end{aligned}
E F G = ( C − A ) t + A = ( D − C ) t + C = ( B − D ) t + D
H H H 可以看作以 A A A 为起点、D D D 为终点、C C C 为控制点的二阶贝塞尔曲线上的点,I I I 可以看作以 C C C 为起点、B B B 为终点、D D D 为控制点的二阶贝塞尔曲线上的点,所以由二阶贝塞尔曲线公式可得:
H = ( F − E ) t + E = ( 1 − t ) 2 A + t 2 D + 2 t ( 1 − t ) C I = ( G − F ) t + F = ( 1 − t ) 2 C + t 2 B + 2 t ( 1 − t ) D J = ( I − H ) t + H = ( ( ( 1 − t ) 2 C + t 2 B + 2 t ( 1 − t ) D ) − ( ( 1 − t ) 2 A + t 2 D + 2 t ( 1 − t ) C ) ) t + ( ( 1 − t ) 2 A + t 2 D + 2 t ( 1 − t ) C ) = ( 1 − t ) 3 A + t 3 B + 3 t ( 1 − t ) 2 C + 3 t 2 ( 1 − t ) D B ( t ) = ( 1 − t ) 3 A + t 3 B + 3 t ( 1 − t ) 2 C + 3 t 2 ( 1 − t ) D , t ∈ [ 0 , 1 ] \begin{aligned}
H &= (F - E)t + E\\
&= (1 - t)^2A + t^2D + 2t(1 - t)C\\
\\
I &= (G - F)t + F\\
&= (1 - t)^2C + t^2B + 2t(1 - t)D\\
\\
J &= (I - H)t + H\\
&= (((1 - t)^2C + t^2B + 2t(1 - t)D) - ((1 - t)^2A + t^2D + 2t(1 - t)C))t + ((1 - t)^2A + t^2D + 2t(1 - t)C)\\
&= (1 - t)^3A + t^3B + 3t(1 - t)^2C + 3t^2(1 - t)D\\
\\
B(t) &= (1 - t)^3A + t^3B + 3t(1 - t)^2C + 3t^2(1 - t)D, t \in [0, 1]
\end{aligned}
H I J B ( t ) = ( F − E ) t + E = ( 1 − t ) 2 A + t 2 D + 2 t ( 1 − t ) C = ( G − F ) t + F = ( 1 − t ) 2 C + t 2 B + 2 t ( 1 − t ) D = ( I − H ) t + H = ((( 1 − t ) 2 C + t 2 B + 2 t ( 1 − t ) D ) − (( 1 − t ) 2 A + t 2 D + 2 t ( 1 − t ) C )) t + (( 1 − t ) 2 A + t 2 D + 2 t ( 1 − t ) C ) = ( 1 − t ) 3 A + t 3 B + 3 t ( 1 − t ) 2 C + 3 t 2 ( 1 − t ) D = ( 1 − t ) 3 A + t 3 B + 3 t ( 1 − t ) 2 C + 3 t 2 ( 1 − t ) D , t ∈ [ 0 , 1 ]
或者 J J J 也可以看作以 E E E 为起点、G G G 为终点、F F F 为控制点的二阶贝塞尔曲线上的点,由二阶贝塞尔曲线公式可得:
E = ( C − A ) t + A F = ( D − C ) t + C G = ( B − D ) t + D J = ( 1 − t ) 2 E + t 2 G + 2 t ( 1 − t ) F = ( 1 − t ) 2 ( ( C − A ) t + A ) + t 2 ( ( B − D ) t + D ) + 2 t ( 1 − t ) ( ( D − C ) t + C ) = ( 1 − t ) 3 A + t 3 B + 3 t ( 1 − t ) 2 C + 3 t 2 ( 1 − t ) D B ( t ) = ( 1 − t ) 3 A + t 3 B + 3 t ( 1 − t ) 2 C + 3 t 2 ( 1 − t ) D , t ∈ [ 0 , 1 ] \begin{aligned}
E &= (C - A)t + A\\
F &= (D - C)t + C\\
G &= (B - D)t + D\\
J &= (1 - t)^2E + t^2G + 2t(1 - t)F\\
&= (1 - t)^2((C - A)t + A) + t^2((B - D)t + D) + 2t(1 - t)((D - C)t + C)\\
&= (1 - t)^3A + t^3B + 3t(1 - t)^2C + 3t^2(1 - t)D\\
\\
B(t) &= (1 - t)^3A + t^3B + 3t(1 - t)^2C + 3t^2(1 - t)D, t \in [0, 1]
\end{aligned}
E F G J B ( t ) = ( C − A ) t + A = ( D − C ) t + C = ( B − D ) t + D = ( 1 − t ) 2 E + t 2 G + 2 t ( 1 − t ) F = ( 1 − t ) 2 (( C − A ) t + A ) + t 2 (( B − D ) t + D ) + 2 t ( 1 − t ) (( D − C ) t + C ) = ( 1 − t ) 3 A + t 3 B + 3 t ( 1 − t ) 2 C + 3 t 2 ( 1 − t ) D = ( 1 − t ) 3 A + t 3 B + 3 t ( 1 − t ) 2 C + 3 t 2 ( 1 − t ) D , t ∈ [ 0 , 1 ]
阶梯插值函数
step 函数的逻辑是
1 2 3 4 5 6 step(a, x){ if(x < a) return 0; else return 1; }
平滑阶梯插值函数
smoothstep 函数可以用来生成 0 到 1 的平滑过渡值,它也叫平滑阶梯函数。smoothstep 函数的定义是
1 2 3 4 5 float smoothstep(float a, float b, float x) { x = clamp((x - a) / (b- a), 0.0, 1.0); return x * x * (3 - 2 * x); }
简单来说就是:
在 a < b 的情况下,当 x < a 时,返回 0,当 x > b 时,返回 1,否则在 0 和 1 之间平滑过渡:
在 a > b 的情况下,当 x < b 时,返回 1,当 x > a 时,返回 0,否则在 0 和 1 之间平滑过渡:
两个 smoothstep 进行减法运算可以得到一些波形图,例如 smoothstep(1, 2, x) - smoothstep(2, 3, x):
想要增加波峰的持续宽度,可以构造 smoothstep(1, 2, x) - smoothstep(3, 4, x):