中EN
概念页

贝塞尔曲线

Bézier Curves

参数曲线 p(t)\mathbf{p}(t) 用参数 tt 生成连续的点,实时图形中常用于让相机或物体沿预定路径移动(与帧率无关),也用于渲染头发和字体。贝塞尔曲线由反复线性插值(de Casteljau 算法)得到,等价于 Bernstein 多项式加权控制点;多段拼接时要关注 CnC^n / GnG^n 连续性。

为什么用参数曲线(17 章引言、17.1 节)

  • 曲线曲面的好处:比三角形更紧凑、可伸缩(可细分成 2 个或 2000 个三角形,天然的 LOD)、更平滑,动画和碰撞检测可能更简单(只需动画少量控制点)。
  • 例:相机要在 1 秒内从一点移到另一点,每帧 50 ms 时取 20 个位置,25 ms 时取 40 个,参数曲线都能给出。线性插值 p(t)=(1−t)p0+tp1\mathbf{p}(t)=(1-t)\mathbf{p}_0+t\mathbf{p}_1 在多点之间会在接点处突然"抖动",因此需要更平滑的曲线。朝向插值见 四元数。

de Casteljau 算法(17.1.1 节)

贝塞尔曲线由 de Casteljau 和 Bézier 为法国汽车工业各自独立发明,因 Bézier 先公开发表而得名。三个控制点 a,b,c\mathbf{a},\mathbf{b},\mathbf{c} 时,先在 ab\mathbf{a}\mathbf{b}、bc\mathbf{b}\mathbf{c} 上按 tt 插值出 d,e\mathbf{d},\mathbf{e},再在 de\mathbf{d}\mathbf{e} 上插值: p(t)=(1−t)2a+2(1−t)t b+t2c\mathbf{p}(t) = (1-t)^2\mathbf{a} + 2(1-t)t\,\mathbf{b} + t^2\mathbf{c} 一般地,n+1n+1 个控制点给出 nn 次曲线,递推为 pik(t)=(1−t) pik−1(t)+t pi+1k−1(t),k=1…n, i=0…n−k\mathbf{p}_i^k(t) = (1-t)\,\mathbf{p}_i^{k-1}(t) + t\,\mathbf{p}_{i+1}^{k-1}(t),\quad k=1\dots n,\ i=0\dots n-k 曲线点为 p(t)=p0n(t)\mathbf{p}(t)=\mathbf{p}_0^n(t)。

flowchart BT
  P0[p0] --> A1[p0^1]
  P1[p1] --> A1
  P1 --> B1[p1^1]
  P2[p2] --> B1
  A1 --> C[p0^2 = p t]
  B1 --> C

上图(自下而上读)是二次曲线的递推三角:每一层由下一层相邻两点按 (1−t)(1-t)、tt 加权得到。

Bernstein 形式

p(t)=∑i=0nBin(t) pi,Bin(t)=(ni)ti(1−t)n−i\mathbf{p}(t)=\sum_{i=0}^{n} B_i^n(t)\,\mathbf{p}_i,\qquad B_i^n(t)=\binom{n}{i}t^i(1-t)^{n-i}

  • 性质:t∈[0,1]t\in[0,1] 时 Bin(t)∈[0,1]B_i^n(t)\in[0,1],且 ∑iBin(t)=1\sum_i B_i^n(t)=1,所以曲线位于控制点的凸包内(便于求包围体);插值两个端点;在 t=0t=0 处与 p1−p0\mathbf{p}_1-\mathbf{p}_0 相切,在 t=1t=1 处与 pn−pn−1\mathbf{p}_n-\mathbf{p}_{n-1} 相切;先变换控制点再求曲线点等价且更快。
  • 三次曲线: p(t)=(1−t)3p0+3t(1−t)2p1+3t2(1−t)p2+t3p3\mathbf{p}(t)=(1-t)^3\mathbf{p}_0+3t(1-t)^2\mathbf{p}_1+3t^2(1-t)\mathbf{p}_2+t^3\mathbf{p}_3 矩阵形式 p(t)=(1tt2t3)(1000−33003−630−13−31)(p0p1p2p3)\mathbf{p}(t)=\begin{pmatrix}1 & t & t^2 & t^3\end{pmatrix}\begin{pmatrix}1&0&0&0\\-3&3&0&0\\3&-6&3&0\\-1&3&-3&1\end{pmatrix}\begin{pmatrix}\mathbf{p}_0\\\mathbf{p}_1\\\mathbf{p}_2\\\mathbf{p}_3\end{pmatrix}
  • 导数仍是贝塞尔曲线,次数低一: ddtp(t)=n∑i=0n−1Bin−1(t)(pi+1−pi)\frac{d}{dt}\mathbf{p}(t)=n\sum_{i=0}^{n-1}B_i^{n-1}(t)(\mathbf{p}_{i+1}-\mathbf{p}_i)
  • 缺点:除端点外不经过控制点;次数随控制点增加而升高,求值越来越贵。解决办法是分段低次曲线。

有理贝塞尔曲线

p(t)=∑i=0nwiBin(t)pi∑i=0nwiBin(t)\mathbf{p}(t)=\frac{\sum_{i=0}^n w_iB_i^n(t)\mathbf{p}_i}{\sum_{i=0}^n w_iB_i^n(t)} 权重 wiw_i 是额外自由度。普通贝塞尔曲线无法精确表示圆,用三段有理贝塞尔曲线可以。

GPU 上的有界贝塞尔曲线 (Loop-Blinn)(17.1.2 节)

填充二次曲线与首尾连线之间的区域:渲染三角形 △p0p1p2\triangle\mathbf{p}_0\mathbf{p}_1\mathbf{p}_2,顶点纹理坐标分别为 (0,0)(0,0)、(0.5,0)(0.5,0)、(1,1)(1,1),像素着色器计算 f(u,v)=u2−vf(u,v)=u^2-v,f<0f<0 在内部,否则在外。透视投影下同样得到投影后的曲线。可用于渲染 TrueType 字体(字形由直线和二次贝塞尔曲线组成,"细分"为有界曲线三角形和普通三角形),Loop 与 Blinn 还给出有理二次、三次曲线和抗锯齿方法。详见 文本渲染。

分段曲线与连续性(17.1.3 节)

两段三次曲线 qi\mathbf{q}_i、ri\mathbf{r}_i 以 q3=r0\mathbf{q}_3=\mathbf{r}_0 相接,到达时间 t0,t1,t2t_0, t_1, t_2。第二段的参数要重映射到 [0,1][0,1]: t′=t−t1t2−t1t'=\frac{t-t_1}{t_2-t_1}

  • 切向相接:(r1−r0)=c(q3−q2)(\mathbf{r}_1-\mathbf{r}_0)=c(\mathbf{q}_3-\mathbf{q}_2),c>0c>0。
  • 取 c=t2−t1t1−t0c=\dfrac{t_2-t_1}{t_1-t_0} 得到 C1C^1;时间间隔相等时 c=1c=1。若间隔不等仍用 c=1c=1,形状相同但沿曲线的速度在接点突变。
连续性含义
C0C^0在同一点相接,有突然的"抖动"
G1G^1接点两侧切线平行且同向,长度不限
C1C^1一阶导数连续(含长度),运动速度平滑
CnC^n前 nn 阶导数连续且非零

G1G^1 弱于 C1C^1。三次曲线是能表示 S 形(拐点)的最低次曲线,因此分段曲线常用三次。

PBRT 的视角:开花(Blossoming)(PBRT 4e B.2.8)

  • 三次贝塞尔曲线的开花 (blossom) p(u0,u1,u2)p(u_0,u_1,u_2) 是对称、对每个参数仿射的三元函数,p(u,u,u)p(u,u,u) 就是曲线在 uu 处的值;p(0,0,0)p(0,0,0)、p(0,0,1)p(0,0,1)、p(0,1,1)p(0,1,1)、p(1,1,1)p(1,1,1) 是四个控制点。计算方式就是三层线性插值,每层用不同参数(de Casteljau 的推广),pbrt 用 BlossomCubicBezier() 实现。
  • 用途:区间 [ua,ub][u_a,u_b] 上子曲线的控制点就是 p(ua,ua,ua)p(u_a,u_a,u_a)、p(ua,ua,ub)p(u_a,u_a,u_b)、p(ua,ub,ub)p(u_a,u_b,u_b)、p(ub,ub,ub)p(u_b,u_b,u_b)(SubdivideCubicBezier() 中有的直接化为原控制点的简单组合,不必调用开花函数);求值时最后被插值的两个点所连直线就是切线,因此可以同时得到导数。开花由 Ramshaw(1987)提出。
  • 原书问题(参考文献):参考文献中"Ramshaw, R. 1989. Blossoms are polar forms"的名字缩写应为 L.(Lyle Ramshaw,与同页 1987 条一致;见 CAGD 6(4):323–358)。
  1. realtime_rendering_4ed.pdf 第 17 章 Curves and Curved Surfaces
  2. PBRT 4e source excerpt: chapter B (Utilities)
  3. Pharr, Jakob, Humphreys《Physically Based Rendering: From Theory to Implementation》第 4 版(MIT Press, 2023)附录 B B.2–B.7 节与延伸阅读,pbr-book.org/4ed/Utilities

相关页面

游戏数学埃尔米特与 Kochanek-Bartels 样条Hermite & Kochanek-Bartels Splines三次 Hermite 曲线用两个端点和两个端点切线定义,比贝塞尔控制点更直观;把多段 Hermite 曲线串起来经过一系列点时,Kochanek-Bartels 用张力、偏置、连续性三个参数从相邻弦计算切线,默认参数即 Catmull-Rom 样条。均匀三次 B 样条则以不经过控制点为代价换来处处 C^2 连续。图形学参数曲面与贝塞尔面片Parametric Surfaces & Bézier Patches参数曲面把参数曲线从一个参数推广到两个参数 (u,v),由少量控制点定义,运行时细分成任意多个三角形,是质量与速度之间的天然权衡:三角形多则着色和轮廓更好。矩形定义域的是贝塞尔面片(张量积曲面),三角形定义域的是贝塞尔三角形,后者是 PN 三角形和 Phong 细分的基础。图形学细分曲线与细分曲面Subdivision Curves & Surfaces细分从一个控制多边形 / 控制网格出发,反复"细化 + 平滑",极限是光滑的曲线或曲面。它能从任意拓扑的网格得到连续、无裂缝的曲面,规则简单、天然支持无限 LOD,连接了离散三角网格与连续曲面。游戏和电影最常用的是 Catmull-Clark(四边形)和 Loop(三角形)两种逼近型方案,可扩展出折痕和置换细分。游戏数学四元数Quaternion单位四元数可以紧凑地表示任意三维旋转,与轴-角表示互相转换很简单,并能做稳定、匀速的朝向插值(slerp),这些都是欧拉角做不好的。它可以高效地转换为矩阵以便与其他变换合并。图形学文本渲染Text Rendering文本中一个像素的变化就可能把 "l" 变成 "1",因此字形渲染格外讲究。主要路线有:按字号预生成字形位图纹理(配合微调和子像素渲染)、有符号距离场纹理(可在三维表面任意缩放旋转)、以及在 GPU 上直接求值字形曲线。图形学毛发渲染Hair & Fur Rendering毛发由角质层、皮质、髓质三层构成,可看作用曲线离散化的体积。几何上用沿引导曲线挤出的四边形条带并配合 alpha/顺序无关透明;着色用 BSDF(R、TT、TRT 分量),再加体积自阴影与多次散射近似;动物短毛可用壳与鳍或几何着色器挤出(RTR4 14.7 节)。游戏开发 · UE5PCG 程序化内容生成框架PCG FrameworkPCG 框架把程序化内容表达为「点流」:PCG 组件/体积从关卡采样空间数据,图中的 Sampler 生成带变换、密度、种子与自定义属性的点,经过滤与变换后由 Spawner 生成网格或 Actor,编辑器中实时更新,也可运行时生成。属性分为 $ 静态属性和元数据动态属性,按 @Data/@Points/@Elements 域组织;图参数与图实例的用法类似材质参数与材质实例;与世界分区集成,生成物继承数据层与 HLOD 层。游戏开发动画混合Animation Blending动画混合把两个或多个输入姿势合成一个输出姿势。基本工具是对每个关节的局部 SRT 分别做 lerp(旋转用 nlerp 或 slerp);在此之上有时间插值、交叉淡入淡出、方向移动、一维/二维混合空间、部分骨骼混合和叠加混合(差分片段)。前几种都是加权平均,叠加混合则是"加上一段变化"(GEA4 卷 II 13.6)。

输入关键词开始搜索

滚轮或双指缩放 · 拖动平移 · 双击放大 / 还原