Skip to content

向量与线性代数

在计算机图形学中,无论是构建三维几何模型、模拟光线传播,还是进行相机的视图变换,其底层运算都深度依赖于线性代数理论。图形学本质上是一场在离散数据与连续空间之间建立映射的工程,而向量 (Vector) 矩阵 (Matrix) 是这场映射的核心数学语言。

本章将系统性地阐述计算机图形学中所必需的线性代数基础知识。我们将摒弃纯数学领域过于抽象的推导,转而聚焦于这些数学工具在图形学渲染管线(Rendering Pipeline)中的几何直觉物理应用。掌握本章内容是理解后续光栅化算法、空间变换及复杂光照模型不可或缺的先决条件。


在几何层面,向量 (Vector) 一个同时具备方向 (Direction) 模长 (Magnitude) 数学实体,通常用带有箭头的字母表示,如 v\vec{v} 或使用粗体 v\mathbf{v}

必须明确的是,在图形学中,向量不包含绝对位置信息。向量 A\vec{A} 和向量 B\vec{B} 如果长度相等且方向一致,那么无论它们在空间中的起点位于何处,它们在数学上都是完全等价的。相对地,表示空间特定位置的实体称为点 (Point)。理解“向量表示方向与位移”而“点表示位置”是构建图形学空间直觉的第一步。由点 AA 指向点 BB 的向量可表示为 AB=BA\vec{AB} = B - A

为了在计算机内部进行数值计算,必须将抽象的几何向量置于特定的笛卡尔坐标系(Cartesian Coordinate System)中。在三维空间内,向量 v\vec{v} 可被唯一地分解为沿三个正交坐标轴(X, Y, Z)的标量分量:

v=(xyz)\vec{v} = \begin{pmatrix} x \\ y \\ z \end{pmatrix}

在图形API(如 OpenGL/GLSL)中,通常对应 vec3 类型的数据结构。

3. 向量的模长与归一化 (Normalization)

Section titled “3. 向量的模长与归一化 (Normalization)”

向量 v\vec{v} 的模长(即几何长度)记作 v||\vec{v}||,在三维直角坐标系中,基于勾股定理可定义为:

v=x2+y2+z2||\vec{v}|| = \sqrt{x^2 + y^2 + z^2}

在诸多图形学计算(如光照计算、方向判定)中,我们往往只关注向量的方向而忽略其物理长度。此时,需要执行归一化 (Normalization) 作。归一化是指将任意非零向量除以其自身模长,从而生成一个方向不变、模长严格为 11单位向量 (Unit Vector),通常记作 v^\hat{v}

v^=vv\hat{v} = \frac{\vec{v}}{||\vec{v}||}

向量的加减法在代数上表现为各分量独立地对应相加或相减:

a±b=(xa±xbya±ybza±zb)\vec{a} \pm \vec{b} = \begin{pmatrix} x_a \pm x_b \\ y_a \pm y_b \\ z_a \pm z_b \end{pmatrix}

在几何层面,加法遵循平行四边形法则 (Parallelogram Law)三角形法则 (Triangle Law)。而减法 ba\vec{b} - \vec{a} 在几何上十分重要:它代表了从向量 a\vec{a} 的终点指向向量 b\vec{b} 终点的位移向量。这一特性在求解射线方向、相机观察方向时被频繁使用。

平行四边形法则


向量点乘 (Dot Product / Scalar Product)

Section titled “向量点乘 (Dot Product / Scalar Product)”

点乘 (Dot Product) 两个向量之间的一种二元运算,其输入为两个向量,输出为一个标量 (Scalar) 即一个实数)。其几何定义为两个向量的模长乘以它们夹角 θ\theta 的余弦值:

ab=abcosθ\vec{a} \cdot \vec{b} = ||\vec{a}|| ||\vec{b}|| \cos\theta

点乘的几何投影

在笛卡尔坐标系下,点乘的代数计算极为高效,为各对应分量乘积之和:

ab=xaxb+yayb+zazb\vec{a} \cdot \vec{b} = x_a x_b + y_a y_b + z_a z_b

2. 在计算机图形学中的核心应用

Section titled “2. 在计算机图形学中的核心应用”

点乘在图形渲染中具有不可替代的作用,核心原因在于它建立了一种高效的计算方式来评估两个方向的投影与接近程度

(1)夹角计算与方向接近度判定

如果将输入的两个向量预先归一化(即 a^=1||\hat{a}|| = 1b^=1||\hat{b}|| = 1),点乘公式将坍缩为:

a^b^=cosθ\hat{a} \cdot \hat{b} = \cos\theta

由于余弦函数 cosθ\cos\theta[0,π][0, \pi] 区间内单调递减,点乘结果能直接映射两者的方向关系:

  • a^b^1\hat{a} \cdot \hat{b} \approx 1 时,两向量几乎平行 (Parallel)
  • a^b^=0\hat{a} \cdot \hat{b} = 0 时,两向量严格正交 (Orthogonal / Perpendicular)
  • a^b^1\hat{a} \cdot \hat{b} \approx -1 时,两向量几乎反向平行 (Anti-parallel)

(2)局部光照模型中的漫反射计算 (Lambertian Reflection)

在渲染管线的光照计算阶段,物体表面的明暗程度取决于表面有多“正对”光源。假设 n^\hat{n} 为物体表面的单位法向量,l^\hat{l} 为指向光源的单位方向向量,根据朗伯漫反射定律(Lambert’s Cosine Law),表面接收到的光辐射通量密度与入射光线和法线夹角的余弦值成正比:

Ldiffusemax(n^l^,0)L_{diffuse} \propto \max(\hat{n} \cdot \hat{l}, 0)

其中 max(...,0)\max(..., 0) 的截断操作是为了剔除 n^l^<0\hat{n} \cdot \hat{l} < 0 的情况,即光线从物体背面照射进来、被物体自身遮挡的物理失效场景。

(3)前后方遮挡测试 (Forward/Backward Test)

在游戏引擎逻辑与相机视锥体剔除中,常常需要判断物体 PP 是否在观察者 OO 的视野前方。通过计算观察者的朝向向量 F\vec{F} 与指向物体的位移向量 OP\vec{OP} 的点乘。如果 FOP>0\vec{F} \cdot \vec{OP} > 0,则物体位于观察者前方半空间内。

点乘在几何上的另一大绝对核心应用是计算向量的投影。在物理引擎(如碰撞后的速度分解、沿斜面滑动)或着色器编程中,我们经常需要将一个向量 a\vec{a} “拆解”为平行于另一个向量 b\vec{b} 的分量和垂直于 b\vec{b} 的分量。

a\vec{a} 投影到 b\vec{b} 上所产生的平行向量分量,通常记作 projba\text{proj}_{\vec{b}} \vec{a}。其计算公式直接延展自点乘的代数结果:

projba=(abb2)b\text{proj}_{\vec{b}} \vec{a} = \left( \frac{\vec{a} \cdot \vec{b}}{||\vec{b}||^2} \right) \vec{b}

如果作为被投影底座的 b\vec{b} 已经被提前归一化为了单位向量 b^\hat{b},由于 b^2=1||\hat{b}||^2 = 1, 投影公式会坍缩得更加简洁:

projb^a=(ab^)b^\text{proj}_{\hat{b}} \vec{a} = (\vec{a} \cdot \hat{b}) \hat{b}

在这个公式中,标量部分 (ab^)(\vec{a} \cdot \hat{b}) 计算出了投影的标量长度 (Scalar Length),而向量部分 b^\hat{b} 赋予了这截长度以准确的方向。你甚至可以在前文的《点乘的几何投影》图解中直观地看到这截绿色的投影向量。

我们来看一个具体的二维判定例子。 假设虚拟场景中,玩家控制的角色位于原点,其正视线方向为归一化向量 v=(0,1)\vec{v} = (0, 1)。此时前方存在一只怪物,相对于玩家的位移向量为 m=(1,1)\vec{m} = (1, 1)。系统需要判定该怪物是否在玩家的“前方视野”半区内。

  1. 执行点乘计算:根据代数公式,将对应分量相乘并求和:vm=(0×1)+(1×1)=1\vec{v} \cdot \vec{m} = (0 \times 1) + (1 \times 1) = 1
  2. 分析结果符号:由于计算结果 1>01 > 0,这说明两者的夹角余弦值为正。
  3. 得出物理结论:由于余弦值为正,说明玩家视线与怪物位移方向的夹角小于 9090^\circ。因此,这只怪物确实位于玩家的前方半空间内。这种用乘法替代角度计算的技巧,计算效率高,且在引擎底层执行频繁。

向量叉乘 (Cross Product / Vector Product)

Section titled “向量叉乘 (Cross Product / Vector Product)”

与点乘输出标量不同,叉乘 (Cross Product) 入两个三维向量,输出一个全新的三维向量。叉乘所得的向量在空间中具有极强的几何属性:它同时垂直(正交)于参与运算的原始两个向量

叉乘所得向量的模长定义为:

a×b=absinθ||\vec{a} \times \vec{b}|| = ||\vec{a}|| ||\vec{b}|| \sin\theta

几何上,该模长等价于由向量 a\vec{a}b\vec{b} 构成的平行四边形的面积。

叉乘向量的方向由右手定则 (Right-hand Rule) 格判定:伸出右手,将四指由向量 a\vec{a} 的方向卷曲握向向量 b\vec{b} 的方向(取小于 180180^\circ 的夹角),此时伸直的大拇指所指的方向即为 a×b\vec{a} \times \vec{b} 的方向。

在笛卡尔坐标系下,叉乘通过行列式形式进行代数计算:

a×b=(yazbzaybzaxbxazbxaybyaxb)\vec{a} \times \vec{b} = \begin{pmatrix} y_a z_b - z_a y_b \\ z_a x_b - x_a z_b \\ x_a y_b - y_a x_b \end{pmatrix}

3. 在计算机图形学中的核心应用

Section titled “3. 在计算机图形学中的核心应用”

(1)法向量生成 (Normal Vector Generation)

在计算机图形学中,多边形网格通常由海量的三角形图元构成。给定三角形的三个顶点 A,B,CA, B, C,可以通过构造两个边缘向量 e1=BA\vec{e_1} = B - Ae2=CA\vec{e_2} = C - A,并对其执行叉乘操作,直接获取垂直于该三角形平面的表面法向量 N\vec{N}

N=e1×e2\vec{N} = \vec{e_1} \times \vec{e_2}

(注:实际渲染管线中需对其执行归一化 N^=NN\hat{N} = \frac{\vec{N}}{||\vec{N}||})

(2)内外测试与光栅化算法 (Inside/Outside Test)

在光栅化阶段(Rasterization),核心任务之一是判定屏幕上的一个像素中心点 PP 是否位于由顶点 A,B,CA, B, C 构成的三角形内部。

利用叉乘的右手定则特性,判定流程如下:

  1. 构造边缘向量:按逆时针(或顺时针)顺序,构造三角形的三条边缘向量 AB\vec{AB}BC\vec{BC}CA\vec{CA}
  2. 构造测试向量:构造从每个顶点指向目标像素中心点 PP 的向量 AP\vec{AP}BP\vec{BP}CP\vec{CP}
  3. 计算空间叉乘:分别计算边缘向量与测试向量的叉乘,即 AB×AP\vec{AB} \times \vec{AP}BC×BP\vec{BC} \times \vec{BP}CA×CP\vec{CA} \times \vec{CP}
  4. 验证符号一致性:若 PP 严格位于三角形内部,则这三个叉乘结果向量的 Z 轴分量将具有相同的符号(同正或同负)。若出现符号不一致,则 PP 点在三角形外部。

这一机制是基于扫描线算法或包围盒遍历的光栅化算法的底层基石。

(3)左右方位判定 (Left/Right Test)

叉乘还能判定向量 b\vec{b} 位于向量 a\vec{a} 的“左侧”还是“右侧”。通过计算二者的叉乘,若结果向量指向屏幕外侧(Z 为正),则 b\vec{b} 位于 a\vec{a} 左侧(逆时针方);若指向屏幕内侧,则为右侧。这在碰撞检测和多边形凹凸性判断中广泛应用。

在三维空间中,我们经常需要依靠已有向量来构建完整的坐标轴。假设在笛卡尔坐标系中,已知 X 轴方向的单位向量 x=(1,0,0)\vec{x} = (1, 0, 0),以及 Y 轴方向的单位向量 y=(0,1,0)\vec{y} = (0, 1, 0)。我们来看看叉乘能算出什么。

  1. 套用行列式公式:根据公式 x×y\vec{x} \times \vec{y}(yxzyzxyyzxxyxxzyxxyyyxxy)=(0×00×10×01×01×10×0)\begin{pmatrix} y_x z_y - z_x y_y \\ z_x x_y - x_x z_y \\ x_x y_y - y_x x_y \end{pmatrix} = \begin{pmatrix} 0\times0 - 0\times1 \\ 0\times0 - 1\times0 \\ 1\times1 - 0\times0 \end{pmatrix}
  2. 得出结果:通过简单的加减,我们得到了结果向量 z=(0,0,1)\vec{z} = (0, 0, 1)
  3. 几何意义验证:计算结果精确地生成了 Z 轴单位向量 (0,0,1)(0, 0, 1)。在底层图形引擎中,我们正是利用这种叉乘特性,通过两个已知方向来自动推导出第三个完全垂直的方向,从而轻松构建出完整的三维坐标系或推导多边形的表面法线。

正交基与局部坐标系 (Orthonormal Bases)

Section titled “正交基与局部坐标系 (Orthonormal Bases)”

图形学渲染本质上是数据在多个坐标系(模型空间、世界空间、观察空间)之间的反复投影与映射。而定义任何一个三维空间坐标系,都需要一组基向量(Basis Vectors)

当且仅当一组向量 u,v,w\vec{u}, \vec{v}, \vec{w} 满足以下两个条件时,它们构成一组严密的正交基 (Orthogonal Basis)

  1. 互相正交uv=vw=wu=0\vec{u} \cdot \vec{v} = \vec{v} \cdot \vec{w} = \vec{w} \cdot \vec{u} = 0
  2. 模长归一化u=v=w=1||\vec{u}|| = ||\vec{v}|| = ||\vec{w}|| = 1

在相机矩阵(View Matrix)或切线空间(Tangent Space)构建过程中,我们经常需要基于局部信息推导出一套局部正交坐标系 {Right,Up,Forward}\{\vec{Right}, \vec{Up}, \vec{Forward}\}。其构建流程(施密特正交化过程 Gram-Schmidt Orthogonalization 的工程变体)通常如下:

  1. 确立前向基准:给定一个目标观察方向作为前向向量 w\vec{w}(并将其归一化)。
  2. 引入辅助参考:引入一个粗略的全局“向上向量” up\vec{up}(通常为世界坐标系的 Y 轴 (0,1,0)(0, 1, 0))。
  3. 叉乘求取右侧向量:计算右侧向量 u=up×w\vec{u} = \vec{up} \times \vec{w}(并将其归一化)。由于叉乘性质,此时 u\vec{u} 严格垂直于 up\vec{up}w\vec{w} 构成的平面。
  4. 反向叉乘修正向上向量:虽然最初的 up\vec{up} 帮助我们求出了 u\vec{u},但它不一定严格垂直于 w\vec{w}。因此,重新计算真正的向上向量 v=w×u\vec{v} = \vec{w} \times \vec{u}。此时,u,v,w\vec{u}, \vec{v}, \vec{w} 构成了严格的正交规范基。

在图形学中,如果向量是被处理的数据(Data),那么矩阵(Matrix)则是施加于这些数据之上的操作符(Operators/Transformations)

矩阵本质上是一个包含实数项的二维数组。一个 m×nm \times n 的矩阵包含 mm 行与 nn 列。在三维图形学中,由于需要引入齐次坐标(Homogeneous Coordinates)以统一表示平移与线性变换,最常用的是 4×44 \times 4 方阵。

矩阵乘法是图形空间变换的核心操作。矩阵 AA 与矩阵 BB 能够相乘的前提是:AA 的列数必须等于 BB 的行数。若 AAm×nm \times n 矩阵,BBn×pn \times p 矩阵,则其乘积 C=ABC = AB 将是一个 m×pm \times p 的矩阵。 乘积矩阵中位于 iijj 列的元素 Ci,jC_{i,j},等于矩阵 AA 的第 ii 行向量与矩阵 BB 的第 jj 列向量的点乘结果。

非交换性(Non-commutativity): 在绝大多数情况下,ABBAA B \neq B A。在几何直觉上,这解释了为何“先旋转后平移”与“先平移后旋转”会导致完全不同的最终位姿。在渲染引擎中编写变换代码时,务必严格遵循矩阵乘法的顺序约定(具体因 API 采用列向量或行向量为主导而异)。

转置矩阵 (Transpose Matrix):将原矩阵 AA 的行与列互换,记为 ATA^T。即 Ai,jT=Aj,iA^T_{i,j} = A_{j,i}。 矩阵乘法的转置遵循倒置规则: (AB)T=BTAT(AB)^T = B^T A^T

单位矩阵 (Identity Matrix):对角线元素全为 11、其余元素全为 00 的方阵,记作 II。它相当于乘法运算中的实数 11。对任意矩阵 AA,有 AI=IA=AAI = IA = A。在图形程序初始化模型变换矩阵时,将其置为单位矩阵是不可省略的安全步骤,表示“无任何空间变换”。

若存在方阵 AA 和方阵 BB 使得 AB=IAB = I,则称 BBAA逆矩阵,记作 A1A^{-1}。 在图形学中,逆矩阵代表了撤销某次空间变换的过程。如果一个矩阵 MM 代表将模型从局部空间映射到世界空间,那么它的逆矩阵 M1M^{-1} 就代表了将其从世界空间反向拉回到局部空间的过程。 逆矩阵的乘法同样遵循倒置分解: (AB)1=B1A1(AB)^{-1} = B^{-1} A^{-1} 值得注意的是,对于特殊的正交矩阵 (Orthogonal Matrix),其逆矩阵恰好等于其转置矩阵(A1=ATA^{-1} = A^T)。相机视图矩阵的旋转部分即是一个正交矩阵,利用此性质可极大地避免高开销的矩阵求逆运算。

在将向量与矩阵进行乘法运算时,必须将三维向量升格为单行或单列的矩阵。在图形学界,存在两种截然不同的向量主导约定:

这是学术界、GAMES101 以及 OpenGL / Vulkan 的标准约定。 向量被表示为 n×1n \times 1 的矩阵。对向量施加变换矩阵 MM 的操作记为:

v=Mv\vec{v'} = M \vec{v}

若存在连续变换序列,操作将在左侧累加:M3M2M1vM_3 M_2 M_1 \vec{v}。其解读顺序为从右向左,即先应用 M1M_1,再应用 M2M_2,最后应用 M3M_3

矩阵到底是如何实现几何旋转的?我们以一个简单的二维空间为例。假设在 X 轴上有一个点 P(1,0)P(1, 0),现在我们需要将其绕原点逆时针旋转 9090^\circ

  1. 构建旋转矩阵:在图形学中,逆时针旋转 9090^\circ 的二维标准矩阵 MM 被定义为 (0110)\begin{pmatrix} 0 & -1 \\ 1 & 0 \end{pmatrix}
  2. 将点写为列向量:我们将点 PP 组织为列向量数据形式:P=(10)\vec{P} = \begin{pmatrix} 1 \\ 0 \end{pmatrix}
  3. 执行矩阵乘法:将矩阵的行与向量的列进行点积相加: MP=(0×1+(1)×01×1+0×0)=(01)M \vec{P} = \begin{pmatrix} 0\times1 + (-1)\times0 \\ 1\times1 + 0\times0 \end{pmatrix} = \begin{pmatrix} 0 \\ 1 \end{pmatrix}
  4. 几何映射结论:计算结果显示,点 PP 的新坐标变成了 (0,1)(0, 1),准确地落在了 Y 轴上。这就意味着,原本需要用到三角函数推导的几何旋转动作,通过预先定义好的旋转矩阵,只需要做几次简单的乘法和加法就能得出结果。这也是为什么矩阵在图形学中如此核心——它把复杂的几何变换变成了一套可以交给 GPU 批量高效处理的加乘运算。

二维空间矩阵旋转映射


本章为后续探讨计算机图形学架构奠定了核心数学基石。请务必牢记以下核心结论:

  1. 向量表示空间中的位移与方向(与原点无关),点乘用于评估方向间的平行或垂直关系,叉乘用于生成空间法线与判断手性方位。
  2. 线性代数赋予了图形学在离散数据上执行批量空间变换的能力。
  3. 矩阵乘法本质是基底空间的线性映射,深刻理解其非交换性与乘积倒置规则,是规避三维渲染错误的核心。

在掌握这些严密的数学工具后,下一章我们将探讨如何利用矩阵对三维空间中的模型执行精确的平移、缩放与旋转变换。