开场
几何(Geometry)是计算机图形学的基础。渲染系统要处理物体形状、相机位置、光照方向、表面法向量和像素插值,这些都需要清楚区分标量、向量和点。
这一讲的重点不是抽象代数本身,而是建立图形学里最常用的一套计算语言:哪些对象可以相加,哪些对象不能随便相加,怎样表示线段、三角形和平面,以及为什么重心坐标可以用于插值。
标量
标量(Scalar)就是实数。它可以进行加法和乘法,并满足结合律、交换律、单位元和逆元等基本性质。
标量本身没有方向,也没有空间位置。长度、时间、质量、颜色通道值和插值系数都可以是标量。它们在几何计算中经常用来缩放向量、混合点或控制参数范围。
向量
向量(Vector)可以从物理上理解为同时具有方向和大小的量。力、速度和有向线段都是向量。图形学里最常见的向量是有向线段,因为它可以表达方向、位移、法向量和观察方向。
向量可以首尾相接相加,也可以乘以标量。
向量空间(Vector Space)中的对象要满足一组规则,例如交换律、结合律、零向量、逆向量、标量乘法和分配律。重要的是,向量空间不一定只由箭头构成。多项式、函数和图像在合适定义下也可以形成向量空间。
图形学中的常用向量
图形学中经常出现三类方向向量。
| 向量 | 含义 | 用途 |
|---|---|---|
| 光照向量(Light Vector) | 指向光源或沿光传播方向的向量 | 计算光照方向 |
| 法向量(Normal Vector) | 垂直于表面的向量 | 计算表面朝向和亮度 |
| 观察向量(View Vector) | 指向相机或观察者的向量 | 计算视角相关效果 |
在光照模型中,法向量和光照向量之间的角度会影响亮度。表面正对光源时更亮,斜向光源时更暗。
点积和叉积
点积(Dot Product)把两个向量变成一个标量。
$$ \mathbf{v} \cdot \mathbf{w} = \lVert \mathbf{v} \rVert \lVert \mathbf{w} \rVert \cos \theta $$当两个向量都是单位向量时,点积等于夹角余弦。它可以度量一个向量在另一个向量方向上的投影程度。漫反射光照中常见的形式就是
$$ I = I_L k_d(\mathbf{n} \cdot \mathbf{l}) $$其中 $\mathbf{n}$ 是单位法向量,$\mathbf{l}$ 是单位光照方向,$I_L$ 是光源强度,$k_d$ 是漫反射系数。实际实现中通常还会把负值截断为 $0$,因为背向光源的表面不应该得到这部分直接漫反射。
叉积(Cross Product)只对三维向量定义,结果是一个新向量。
$$ \mathbf{v} \times \mathbf{w} $$它的方向垂直于 $\mathbf{v}$ 和 $\mathbf{w}$ 所在平面,大小为
$$ \lVert \mathbf{v} \times \mathbf{w} \rVert = \lVert \mathbf{v} \rVert \lVert \mathbf{w} \rVert \sin \theta $$在三角形网格中,可以用两条边的叉积计算表面法向量。
u = Q - P
v = R - P] B --> C[计算 n = u x v] C --> D[单位化得到法向量] D --> E[用于光照计算]
为什么还需要点
向量只有方向和大小,没有固定位置。两条长度和方向相同的有向线段表示同一个向量,即使它们画在空间中的不同地方。因此,只靠向量不能完整描述几何位置。
点(Point)表示空间中的位置。点和向量之间允许这些操作。
| 表达式 | 结果 | 含义 |
|---|---|---|
| 点 $P$ 减点 $Q$ | 向量 $P - Q$ | 从 $Q$ 指向 $P$ 的位移 |
| 点 $Q$ 加向量 $\mathbf{v}$ | 点 $Q + \mathbf{v}$ | 从 $Q$ 沿位移移动到新位置 |
| 向量加向量 | 向量 | 位移叠加 |
| 点加点 | 通常不直接定义 | 位置不能像位移一样任意相加 |
把点和向量空间放在一起,就得到仿射空间(Affine Space)。图形学中的几何建模主要工作在仿射空间里。
直线、射线和线段
一条直线可以由一个点和一个方向向量表示。
$$ P(\alpha) = P_0 + \alpha \mathbf{d} $$其中 $P_0$ 是直线上的一点,$\mathbf{d}$ 是方向向量,$\alpha$ 是标量参数。当 $\alpha$ 可以取任意实数时,得到整条直线。
如果限制 $\alpha \ge 0$,就得到从 $P_0$ 出发沿方向 $\mathbf{d}$ 延伸的射线(Ray)。如果用两个点 $Q$ 和 $R$ 定义线段,则有
$$ P(\alpha) = Q + \alpha(R - Q) = (1-\alpha)Q + \alpha R $$当 $0 \le \alpha \le 1$ 时,$P(\alpha)$ 正好覆盖连接 $Q$ 和 $R$ 的线段。
凸性和凸包
如果一个对象中任意两点之间的线段也完全落在对象内部,那么这个对象是凸的(Convex)。
凸性定义不依赖具体维度。二维多边形、三维多面体,甚至更高维对象,都可以用同样方式判断。
给定若干点 $P_1, P_2, \ldots, P_n$,仿射和(Affine Sum)写作
$$ P = \alpha_1P_1 + \alpha_2P_2 + \cdots + \alpha_nP_n $$其中
$$ \alpha_1 + \alpha_2 + \cdots + \alpha_n = 1 $$如果进一步要求所有 $\alpha_i \ge 0$,这些点的组合就位于这些点形成的凸包(Convex Hull)中。凸包可以理解为包含这些点的最小凸对象。
平面和三角形
平面可以由一个点和两个不共线向量表示。
$$ N(\alpha, \beta) = R + \alpha \mathbf{u} + \beta \mathbf{v} $$也可以由三个不共线点 $P,Q,R$ 表示。
$$ N(\alpha, \beta) = R + \alpha(Q-R) + \beta(P-R) $$三角形是图形学中最重要的图元之一。很多三维模型最终会被拆成三角形网格,因为三角形总是共面的,几何和插值计算也相对稳定。
从参数角度看,三角形内部的点可以由三个顶点的凸组合表示。这个表示直接引出重心坐标。
重心坐标
重心坐标(Barycentric Coordinates)用三个权重表示三角形内部或平面上的点。对于三角形顶点 $P,Q,R$,点 $T$ 可以写成
$$ T(\alpha_1,\alpha_2,\alpha_3) = \alpha_1P + \alpha_2Q + \alpha_3R $$其中
$$ \alpha_1 + \alpha_2 + \alpha_3 = 1 $$如果点在三角形内部或边界上,还要求
$$ \alpha_i \ge 0 $$面积法可以直观地计算重心坐标。设 $\Delta_{PQR}$ 是整个三角形面积,$\Delta_p,\Delta_q,\Delta_r$ 是由点 $T$ 分割出的三个子三角形面积,则
$$ \alpha_1 = \frac{\Delta_p}{\Delta_{PQR}}, \qquad \alpha_2 = \frac{\Delta_q}{\Delta_{PQR}}, \qquad \alpha_3 = \frac{\Delta_r}{\Delta_{PQR}} $$这些比例之和为 $1$。如果某个比例为 $0$,点就在对应边上;如果某个比例为负,点就在三角形外部。
用叉积计算面积比例
在三维空间中,三角形面积可以通过叉积大小计算。若
$$ \mathbf{u}=R-P,\qquad \mathbf{v}=Q-P,\qquad \mathbf{w}=T-P $$则相关面积可以写成叉积大小的一半。因为计算重心坐标时分子和分母都有 $\frac{1}{2}$,比例里会相互抵消。
一个常见写法是
$$ \alpha_2 = \frac{\lVert \mathbf{u}\times\mathbf{w}\rVert}{\lVert \mathbf{u}\times\mathbf{v}\rVert}, \qquad \alpha_3 = \frac{\lVert \mathbf{v}\times\mathbf{w}\rVert}{\lVert \mathbf{u}\times\mathbf{v}\rVert}, \qquad \alpha_1 = 1-\alpha_2-\alpha_3 $$具体使用时要注意顶点顺序和符号约定。若只用面积大小,可以判断比例大小;若要稳定区分内外,还需要保留有向面积或结合一致的方向约定。
重心坐标的用途
重心坐标最重要的用途是插值。只要顶点上有某种属性,就可以用同一组重心坐标计算三角形内部点的属性。
I1, I2, I3] --> B[重心坐标
a1, a2, a3] B --> C[内部属性
I = a1 I1 + a2 I2 + a3 I3]
Gouraud Shading 就利用这种思想。系统先在三角形顶点计算光照颜色,再用重心坐标把颜色插值到三角形内部。图形管线中的光栅化阶段也需要类似的插值思想,把顶点颜色、法向量或纹理坐标传递到片元位置。
曲线和曲面
直线和三角形来自线性函数。更一般地,曲线可以写成一个参数函数
$$ P(\alpha) $$曲面可以写成两个参数的函数
$$ P(\alpha,\beta) $$如果这些函数是非线性的,就可以表示曲线和曲面。
小结
图形学几何的核心是把对象类型分清楚。标量用于缩放和混合,向量用于方向和位移,点用于位置,仿射空间把点和向量连接起来。直线、射线、线段、平面和三角形都可以用参数方程表示;重心坐标则把三角形内部的点和属性插值统一起来。理解这些基础后,图形管线中的投影、光栅化、光照和纹理映射都会更容易解释。