计算机图形学:【Games101】学习笔记06------几何(曲线和曲面、网格处理)、阴影图
- 前言
- 一、几何(曲线和曲面)
-
- [1.1 显式表示(Explicit Representations)](#1.1 显式表示(Explicit Representations))
- [1.2 曲线(Curves)](#1.2 曲线(Curves))
-
- [1.1.1 贝塞尔曲线(Bézier Curves)](#1.1.1 贝塞尔曲线(Bézier Curves))
- [1.1.2 德卡斯特里奥算法(De Casteljau's algorithm)](#1.1.2 德卡斯特里奥算法(De Casteljau’s algorithm))
- [1.1.3 B样条等(B-splines, etc.)](#1.1.3 B样条等(B-splines, etc.))
- [1.3 曲面(Surface)](#1.3 曲面(Surface))
-
- [1.3.1 贝塞尔曲面(Bezier surfaces)](#1.3.1 贝塞尔曲面(Bezier surfaces))
- [1.3.2 三角形和四边形,细分、简化、正则化(Triangles & quads、Subdivision, simplification, regularization)](#1.3.2 三角形和四边形,细分、简化、正则化(Triangles & quads、Subdivision, simplification, regularization))
- 二、几何(网格处理)、阴影图
-
- [2.1 网格细分 (Mesh Subdivision)](#2.1 网格细分 (Mesh Subdivision))
-
- [2.1.1 Loop 细分 (Loop Subdivision)](#2.1.1 Loop 细分 (Loop Subdivision))
- [2.1.2 Catmull-Clark 细分 (一般网格)](#2.1.2 Catmull-Clark 细分 (一般网格))
- [2.2 网格简化 (Mesh Simplification)](#2.2 网格简化 (Mesh Simplification))
-
- [2.2.1 边坍缩 (Edge Collapsing)](#2.2.1 边坍缩 (Edge Collapsing))
- [2.2.2 二次误差度量 (Quadric Error Metrics)](#2.2.2 二次误差度量 (Quadric Error Metrics))
- [2.2.3 基于二次误差的简化算法 (Simplification via Quadric Error)](#2.2.3 基于二次误差的简化算法 (Simplification via Quadric Error))
- [2.3 阴影映射 (Shadow Mapping)](#2.3 阴影映射 (Shadow Mapping))
-
- [2.3.1 可视化阴影映射(Visualizing Shadow Mapping)](#2.3.1 可视化阴影映射(Visualizing Shadow Mapping))
前言
- 🎮 GAMES101 是国内相当有名的图形学公开课。项目相关资源在:https://sites.cs.ucsb.edu/~lingqi/teaching/games101.html。
- 本 📒笔记为 🖊️笔者在自学过程中整理的 🇨🇳中文版笔记,供各位 📖读者阅读 😼~
一、几何(曲线和曲面)
1.1 显式表示(Explicit Representations)
图形学中的显式表示包括:三角网格(triangle meshes)、贝塞尔曲面(Bezier surfaces)、细分曲面(subdivision surfaces)、NURBS(Non-Uniform Rational B-Splines)、点云(point clouds)。

1、显式点云表示(Point Cloud (Explicit))
点云表示是最简单的表示:点列表(x,y,z)。
优点是轻松表示任何类型的几何形状,适用于大型数据集(远多于1个点/像素),通常被转换为多边形网格。
缺点是在采样不足的区域难以绘制。

2、显式多边形网格(Polygon Mesh (Explicit))
多边形网格存储顶点和多边形(通常是三角形或四边形),或许是图形学中最常见的表示方式。
优点是更易于进行处理/模拟、自适应采样,缺点是需要更复杂的数据结构。

3、Wavefront对象(.obj)文件格式(The Wavefront Object File (.obj) Format)
在图形学研究中常用,只是一个指定顶点、法线、纹理坐标及其连接关系的文本文件。

1.2 曲线(Curves)
曲线无处不在,比如:
1、相机路径(Camera Paths)

2、动画曲线(Animation Curves)

3、矢量字体(Vector Fonts)

1.1.1 贝塞尔曲线(Bézier Curves)
1、用切线定义三次贝塞尔曲线(Defining Cubic Bézier Curve With Tangents)
可以通过切线来定义三次 Bézier 曲线,例如: t 0 = 3 ( p 1 − p 0 ) t_0 = 3(p_1 - p_0) t0=3(p1−p0), t 1 = 3 ( p 3 − p 2 ) t_1 = 3(p_3 - p_2) t1=3(p3−p2)。

1.1.2 德卡斯特里奥算法(De Casteljau's algorithm)
1、评估贝塞尔曲线(德卡斯特里奥算法)(Evaluating Bézier Curves (de Casteljau Algorithm))
由 Pierre Bézier 和 Paul de Casteljau 发明。
算法思想:通过线性插值 (lerp) 逐步插入点。给定一个在 0 , 1 0, 1 0,1 范围内的参数 t t t:在相邻的控制点线段上取比例为 t t t 的点进行连接,然后在新形成的线段上继续递归该插值过程,直到最终收敛得到曲线上的唯一一点。 该算法能运行在所有 0 , 1 0, 1 0,1 范围的 t t t 上以画出完整曲线,无论是二次(3个输入点)还是三次(4个输入点)曲线均适用。
考虑三个点(二次贝塞尔曲线):

使用线性插值插入一个点:

在两边都插入:

递归重复:

对 0,1 中的每个 t 运行相同的算法:

2、三次贝塞尔曲线------德卡斯特里奥算法(Cubic Bézier Curve -- de Casteljau)
总共有四个输入点,进行相同的递归线性插值:

3、可视化德卡斯特里奥算法(Visualizing de Casteljau Algorithm)

4、评估贝塞尔曲线的代数公式(Evaluating Bézier Curves Algebraic Formula)
德卡斯特里奥算法生成一个系数金字塔:每个向右的箭头表示乘以t,每个向左的箭头表示乘以(1--t)。

示例:由三个点构成的二次贝塞尔曲线:

b 0 1 ( t ) = ( 1 − t ) b 0 + t b 1 b 1 1 ( t ) = ( 1 − t ) b 1 + t b 2 b 0 2 ( t ) = ( 1 − t ) b 0 1 + t b 1 1 b_{0}^{1}(t)=(1-t) b_{0}+t b_{1} \\ b_{1}^{1}(t)=(1-t) b_{1}+t b_{2} \\ b_{0}^{2}(t)=(1-t) b_{0}^{1}+t b_{1}^{1} b01(t)=(1−t)b0+tb1b11(t)=(1−t)b1+tb2b02(t)=(1−t)b01+tb11 b 0 2 ( t ) = ( 1 − t ) 2 b 0 + 2 t ( 1 − t ) b 1 + t 2 b 2 b_{0}^{2}(t)=(1-t)^2b_0+2t(1-t)b1+t^2b_2 b02(t)=(1−t)2b0+2t(1−t)b1+t2b2
5、贝塞尔曲线------通用代数公式(Bézier Curve -- General Algebraic Formula)
n阶贝塞尔曲线的伯恩斯坦形式(Bernstein form):
b n ( t ) = ∑ j = 0 n b j B j n ( t ) b^n(t) = \sum_{j=0}^{n}b_j B_j^n(t) bn(t)=j=0∑nbjBjn(t)
其中, B j n ( t ) B_j^n(t) Bjn(t) 是 n 阶 Bernstein 多项式(标量多项式): B i n ( t ) = ( n i ) t i ( 1 − t ) n − i B_i^n(t) = \binom{n}{i} t^i(1-t)^{n-i} Bin(t)=(in)ti(1−t)n−i。 b j b_j bj 则是多维空间中的 Bézier 控制点向量。

示例:假设 n = 3 n=3 n=3,且我们处于 R 3 R^{3} R3 中,即我们可以在3D空间中拥有控制点,例如: b 0 = ( 0 , 2 , 3 ) b_{0}=(0,2,3) b0=(0,2,3)、 b 1 = ( 2 , 3 , 5 ) b_{1}=(2,3,5) b1=(2,3,5)、 b 2 = ( 6 , 7 , 9 ) b_{2}=(6,7,9) b2=(6,7,9), b 3 = ( 3 , 4 , 5 ) b3 = (3, 4, 5) b3=(3,4,5)。
这些点定义了一条3D贝塞尔曲线,它是关于 t 的三次多项式:
b n ( t ) = b 0 ( 1 − t ) 3 + b 1 3 t ( 1 − t ) 2 + b 2 3 t 2 ( 1 − t ) + b 3 t 3 b^{n}(t)=b_{0}(1-t)^{3}+b_{1} 3 t(1-t)^{2}+b_{2} 3 t^{2}(1-t)+b_{3} t^{3} bn(t)=b0(1−t)3+b13t(1−t)2+b23t2(1−t)+b3t3
6、Cubic Bézier Basis Functions(三次贝塞尔基函数)
伯恩斯坦多项式(Bernstein polynomials):
B i n ( t ) = ( n i ) t i ( 1 − t ) n − i B_{i}^{n}(t)=\left(\begin{array}{c}n \\ i\end{array}\right) t^{i}(1-t)^{n-i} Bin(t)=(ni)ti(1−t)n−i

7、贝塞尔曲线的性质(Properties of Bézier Curves)
(1)插值端点(Interpolates endpoints):曲线一定会经过起点和终点。
例如对于三次 Bézier 曲线有:b(0) = b0;b(1) = b3。
(2)与端点线段相切(Tangent to end segments):曲线的起始和末端切线与对应的控制点线段方向一致。
Cubic case: b ′ ( 0 ) = 3 ( b 1 − b 0 ) ; b ′ ( 1 ) = 3 ( b 3 − b 2 ) b'(0)=3\left(b_{1}-b_{0}\right) ; b'(1)=3\left(b_{3}-b_{2}\right) b′(0)=3(b1−b0);b′(1)=3(b3−b2)。
(3)仿射变换性质(Affine transformation property):若要对曲线做仿射变换,只需直接对控制点做仿射变换即可。
通过变换控制点来变换曲线。
(4)凸包性质(Convex hull property):整条曲线永远处于所有控制点所构成的凸包(Convex hull)范围之内。
8、补充:什么是凸包(BTW: What's a Convex Hull)

9、分段贝塞尔曲线(Piecewise Bézier Curves)
高阶贝塞尔曲线(Higher-Order Bézier Curves)很难控制,不常见。

相反,可以将许多低阶贝塞尔曲线连接起来,分段三次贝塞尔曲线是最常用的技术。其应用包括:字体、路径、Illustrator、Keynote等。

演示Demo可以参考:https://math.hws.edu/eck/cs424/notes2013/canvas/bezier.html
10、分段贝塞尔曲线具有连续性(Piecewise Bézier Curve -- Continuity)
对于两条贝塞尔曲线(假设这里是整数分拆,是可以推广的):
a : k , k + 1 → R N b : k + 1 , k + 2 → R N a : k, k+1 \to \mathbb{R}^{N} \\ b : k+1, k+2 \to \mathbb{R}^{N} a:k,k+1→RNb:k+1,k+2→RN

C 0 C^{0} C0 连续性( C 0 C^{0} C0 continuity): a n = b 0 a_{n}=b_{0} an=b0

C 1 C^{1} C1 连续性( C 1 C^{1} C1 continuity): a n = b 0 = 1 2 ( a n − 1 + b 1 ) a_{n}=b_{0}=\frac{1}{2}\left(a_{n-1}+b_{1}\right) an=b0=21(an−1+b1)

1.1.3 B样条等(B-splines, etc.)
1、样条曲线(Spline)
一条连续曲线,其构造方式是通过一组给定的点,并具有一定数量的连续导数。简而言之,一条受控制的曲线。

2、B样条(B-splines)
是Basic splines的缩写。比贝塞尔曲线需要更多信息。满足贝塞尔曲线的所有重要特性(即超集)。
3、重要说明
在本课程中,不涉及B样条和非均匀有理B样条(NURBS),也不涉及曲线的操作(如阶数的增减)。
想要了解更多/更深入的内容,欢迎参考胡事民教授的课程:https://www.bilibili.com/video/av66548502/?from=search&seid=65256805876131485&vd_source=f70630fa5800ae385634e9aaafa4ae1b
1.3 曲面(Surface)
1.3.1 贝塞尔曲面(Bezier surfaces)
可以将贝塞尔曲线扩展到曲面(例如著名的犹他茶壶 (Utah Teapot) 模型)。

1、双三次贝塞尔曲面片(Bicubic Bézier Surface Patch)
贝塞尔曲面和 4 ×4 控制点数组。

可视化双三次贝塞尔曲面片(Visualizing Bicubic Bézier Surface Patch)可以参考:https://acko.net/。

2、评估贝塞尔曲面(Evaluating Bézier Surfaces)
参数 ( u , v ) (u, v) (u,v) 曲面求值计算 :对于给定的在 0 , 1 2 0, 1^2 0,12 范围内的参数 ( u , v ) (u, v) (u,v),求出对应的曲面三维位置。

3、方法:可分离一维德卡斯特里奥算法(Method: Separable 1D de Casteljau Algorithm)
使用可分离的 1D de Casteljau 算法。目标:评估与(u,v)对应的曲面位置------(u,v)可分离的德卡斯特里奥算法应用。
- 首先利用参数 u u u,在水平方向的4条曲线上各自进行 1D de Casteljau 求值,计算出4个对应的点。
- 将这4个新计算出的点作为一条"移动的 Bézier 曲线 (Moving Bezier curve)"的控制点。
- 接着利用参数 v v v,在这条新的"移动曲线"上再次执行 1D de Casteljau 算法,最终得出目标曲面点 ( u , v ) (u, v) (u,v) 的坐标位置。


1.3.2 三角形和四边形,细分、简化、正则化(Triangles & quads、Subdivision, simplification, regularization)
1、网格操作:几何处理(Mesh Operations: Geometry Processing)
- 网格细分(Mesh subdivision)
- 网格简化(Mesh simplification)
- 网格正则化(Mesh regularization)

二、几何(网格处理)、阴影图
本节课主要探讨三种几何处理中的网格操作:
- 网格细分 (Mesh subdivision):上采样 (upsampling),增加分辨率。

- 网格简化 (Mesh simplification):下采样 (downsampling),降低分辨率,但尽量保持原有的形状和外观。

- 网格正则化 (Mesh regularization) :保持三角形数量不变,通过修改采样点的分布来提高网格质量。

2.1 网格细分 (Mesh Subdivision)
2.1.1 Loop 细分 (Loop Subdivision)
Loop 细分是针对三角形网格的一种常见细分规则。
步骤:首先将每个三角形分裂成四个新的小三角形(增加顶点),然后调整它们的位置。



位置更新规则(新老顶点更新方式不同):
- 新顶点 (New vertex) :假设新顶点位于共享边上,其周围的四个顶点分别为 A、B、C、D(其中 A、B 在共享边上,C、D 为对角顶点),则新顶点的位置更新为: 3 / 8 ∗ ( A + B ) + 1 / 8 ∗ ( C + D ) 3/8 * (A + B) + 1/8 * (C + D) 3/8∗(A+B)+1/8∗(C+D)。

- 老顶点 (Old vertex) :更新后的位置 = ( 1 − n ∗ u ) ∗ original_position + u ∗ neighbor_position_sum = (1 - n*u) * \text{original\_position} + u * \text{neighbor\_position\_sum} =(1−n∗u)∗original_position+u∗neighbor_position_sum。 其中 n n n 为顶点的度(degree,即连接的边数)。 u u u 的取值为:如果 n = 3 n=3 n=3,则 u = 3 / 16 u = 3/16 u=3/16;否则 u = 3 / ( 8 n ) u = 3/(8n) u=3/(8n)

Loop 细分结果示例:

2.1.2 Catmull-Clark 细分 (一般网格)
适用于一般网格(包含四边形和非四边形面)的细分方法。
核心概念:
- 非四边形面 (Non-quad face) 。
- 奇异点 (Extraordinary vertex):度数不等于 4 的顶点。
每次细分的步骤:
- 在每个面中添加一个顶点(Face point)。
- 在每条边上添加一个中点(Edge point)。
- 连接所有新顶点。

细分一次后的性质:
- 增加的奇异点数量等于原网格中非四边形面的数量。
- 所有非四边形面都会完全消失,网格被全部转化为四边形面。



顶点更新规则 (四边形网格的情况):
- 面点 (Face point) f f f:面上四个顶点的平均值,即 f = ( v 1 + v 2 + v 3 + v 4 ) / 4 f = (v_1+v_2+v_3+v_4)/4 f=(v1+v2+v3+v4)/4。
- 边点 (Edge point) e e e:边两端顶点与相邻两个面点的平均值,即 e = ( v 1 + v 2 + f 1 + f 2 ) / 4 e = (v_1+v_2+f_1+f_2)/4 e=(v1+v2+f1+f2)/4。
- 顶点 (Vertex point) v v v:更新公式为 v = f 1 + f 2 + f 3 + f 4 + 2 ( m 1 + m 2 + m 3 + m 4 ) + 4 p 16 v = \frac{f_1+f_2+f_3+f_4 + 2(m_1+m_2+m_3+m_4) + 4p}{16} v=16f1+f2+f3+f4+2(m1+m2+m3+m4)+4p,其中 p p p 为旧顶点位置, m m m 为相邻边的中点, f f f 为相邻面点。


注意:Catmull-Clark 细分同样可以用于处理带有锐利折痕 (Sharp Creases) 的表面 。皮克斯的动画短片《Geri's Game》就实际应用了细分技术。
2.2 网格简化 (Mesh Simplification)
目标:减少网格元素的数量,同时尽量保持整体的形状不变(例如将 30,000 个三角形简化到 30 个)。

2.2.1 边坍缩 (Edge Collapsing)
网格简化的核心操作是将一条边坍缩成一个顶点。
问题:坍缩后新的顶点应该放在哪里?采用局部平均(local averaging)不是一个好主意。

2.2.2 二次误差度量 (Quadric Error Metrics)
为了衡量简化引入的几何误差,提出了二次误差度量。过计算边坍缩的二次误差来决定其代价。
核心思想:新的顶点位置应该使其到"原来与之相关的各个三角形面"的平方距离之和(L2距离)最小。

2.2.3 基于二次误差的简化算法 (Simplification via Quadric Error)
为每条边根据二次误差度量计算一个"分数"(score)。
贪心算法 (Greedy algorithm):迭代地寻找并坍缩分数最小(即误差最小)的边。
每次坍缩后,受影响的相邻边的分数需要重新计算。该算法能产生非常好的简化效果。

2.3 阴影映射 (Shadow Mapping)
在光栅化中如何绘制阴影?
答案是阴影映射 (Shadow Mapping) ,这是一种纯图像空间 (Image-space) 的算法。
特点:在计算阴影时不需要知道场景的几何信息,但必须处理走样(aliasing)带来的瑕疵。
核心思想:如果一个点不在阴影中,那么它必须既能被光源看到,也能被相机看到。
算法的两趟 Pass:
Pass 1: 从光源视角渲染 (Render from Light)
将虚拟相机放在光源位置看向场景。记录下每个像素可见的最浅深度,生成一张深度图 (Depth image/Shadow map) 。


Pass 2: 从相机视角渲染 (Render from Eye)
Pass 2A:从相机视角正常渲染场景,获取相机视角下的像素点坐标及深度。

Pass 2B (投影回光源):将相机视角下可见的点,重新投影回光源的视角。
深度比较:将在光照空间中计算出的深度,与 Pass 1 中 Shadow map 记录的深度进行对比。如果两者深度一致(近似),说明光能直接照到该点,可见 (VISIBLE) 。

如果重投影的深度大于 Shadow map 记录的深度,说明光线被遮挡了,该点在阴影中 (BLOCKED)。

2.3.1 可视化阴影映射(Visualizing Shadow Mapping)


阴影映射是极为著名的渲染技术,广泛用于早期动画(如玩具总动员)以及每一个 3D 电子游戏中(如《塞尔达传说:旷野之息》、《超级马里奥:奥德赛》)。

存在的问题 (Problems):
- 只能生成硬阴影 (Hard shadows):仅适用于点光源。
- 质量依赖于 Shadow Map 的分辨率:这是图像空间技术的通病,分辨率不够会导致锯齿或块状阴影。
- 浮点数相等比较问题:涉及缩放、偏移 (bias) 和容差 (tolerance) 问题,容易引起自阴影瑕疵 (Shadow acne)。
