插值函数
本文最后更新于:2025年4月17日 下午
线性插值函数
$$
lerp(y_1, y_2, weight) = y_1 + (y_2 - y_1) \times weight
$$
其中 $weight$ 是一个在 [0, 1] 区间的实数,倒不是因为取更大的值后这个函数就无定义了,而是因为取了更大的值,这个函数就失去了我们构造它的理由,另外,CG 会限制 $weight$ 的值在 [0, 1] 的范围内,超过这个范围会被留在边界 0 或者边界 1。
这里 $y_1$ 被称为起点,而 $y_2$ 被称为终点,lerp 函数就是取值 $y_1$ 到 $y_2$ 中间的一个值。取值由 $weight$ 来控制,当 $weight$ 为 0.5 时,取值刚好在起点和终点之间。为了更加方便理解,可以把公式写成这种形式:
$$
lerp(y_1, y_2, weight) = (1 - weight) \times y_1 + weight \times y_2
$$
简单来说,lerp 函数是在 $y_1$ 和 $y_2$ 之间过渡。$y_1$ 和 $y_2$ 可以是一个值,也可以是一个函数。比如,我们可以在正弦函数和线性函数之间做过渡,我们先看一下正弦函数:
再看一下最简单的线性函数 $y = x$
在它俩之间过渡,我们只需要使用 $lerp(\sin x, x, 0.5)$ 即可。当然可以调整 $weight$ 参数观察不同的结果。
当 $y_1$ 和 $y_2$ 分别为两个点时,结果就是两点间的位置。
贝塞尔曲线
当有 $A$、$B$、$C$ 三个点且有 $D$ 为从 $A$ 到 $C$ 上权重为 $t$ 的插值,$E$ 为从 $C$ 到 $B$ 上权重为 $t$ 的插值,点 $F$ 为从 $D$ 到 $E$ 上权重为 $t$ 的插值,则点 $F$ 是以 $A$ 为起点、$B$ 为终点、$C$ 为控制点的二阶贝塞尔曲线上的一点。
同理,当有 $A$、$B$、$C$、$D$ 四个点,$E$ 为从 $A$ 到 $C$ 上权重为 $t$ 的插值,$F$ 为从 $C$ 到 $D$ 上权重为 $t$ 的插值,$G$ 为从 $D$ 到 $B$ 上权重为 $t$ 的插值,且 $H$ 为从 $E$ 到 $F$ 上权重为 $t$ 的插值,$I$ 为从 $F$ 到 $G$ 上权重为 $t$ 的插值,$J$ 为从 $H$ 到 $I$ 上权重为 $t$ 的插值,则点 $J$ 是以 $A$ 为起点、$B$ 为终点、$C$ 和 $D$ 为控制点的三阶贝塞尔曲线上的一点。
二阶贝塞尔曲线公式推导
由 $f(p_0, p_1, t) = (p_1 - p_0) \times t + p_0$ 可得:
$$
\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}
$$
三阶贝塞尔曲线公式推导
由 $f(p_0, p_1, t) = (p_1 - p_0) \times t + p_0$ 可得:
$$
\begin{aligned}
E &= (C - A)t + A\
F &= (D - C)t + C\
G &= (B - D)t + D\
\end{aligned}
$$
$H$ 可以看作以 $A$ 为起点、$D$ 为终点、$C$ 为控制点的二阶贝塞尔曲线上的点,$I$ 可以看作以 $C$ 为起点、$B$ 为终点、$D$ 为控制点的二阶贝塞尔曲线上的点,所以由二阶贝塞尔曲线公式可得:
$$
\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}
$$
或者 $J$ 也可以看作以 $E$ 为起点、$G$ 为终点、$F$ 为控制点的二阶贝塞尔曲线上的点,由二阶贝塞尔曲线公式可得:
$$
\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}
$$
阶梯插值函数
step 函数的逻辑是
1 |
|
平滑阶梯插值函数
smoothstep 函数可以用来生成 0 到 1 的平滑过渡值,它也叫平滑阶梯函数。smoothstep 函数的定义是
1 |
|
简单来说就是:
- 在 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):