0%

DirectX 12 龙书读书笔记(2)

矩阵

mmnn列实数组成的矩形阵列称作规模为 m×nm\times n矩阵 (matrix)M\boldsymbol{M}。矩阵中的数字称作元素(element)或元(entry)。用Mij\boldsymbol{M}_{ij} 表示矩阵中第 ii 行、第 jj 列的元素。

矩阵乘法

m×nm\times n的矩阵 A\boldsymbol{A}n×pn\times p的矩阵 B\boldsymbol{B} 的乘积为规模 m×pm\times p 的矩阵 C\boldsymbol{C}C\boldsymbol{C} 中第 ii 行、第 jj 列的元素为矩阵 A\boldsymbol{A}ii个行向量与矩阵 B\boldsymbol{B}jj个列向量的点积,即:

Cij=Ai,B,j\boldsymbol{C}_{ij}=\boldsymbol{A}_{i,*}\cdot\boldsymbol{B}_{*,j}

向量与矩阵的乘法

向量 u=(x,y,z)\boldsymbol{u}=(x,y,z) 与矩阵 A\boldsymbol{A} 的乘法:

uA=xA1,+yA2,+zA3,\boldsymbol{uA}=x\boldsymbol{A}_{1,*}+y\boldsymbol{A}_{2,*}+z\boldsymbol{A}_{3,*}

实为一种 线性组合 (linear combination),意味着向量与矩阵的乘积uA\boldsymbol{uA} 相当于:向量 u\boldsymbol{u} 的标量系数 xxyyzz 与矩阵 A\boldsymbol{A} 各行向量的线性组合。

转置矩阵

转置矩阵 (transpose matrix)指的是将原矩阵M\boldsymbol{M} 的行和列互换所得到的新矩阵,记作MT\boldsymbol{M}^\boldsymbol{T}

单位矩阵

单位矩阵(identity matrix)是一种主对角线上元素均为 1,其他元素都为 0 的方阵。

行列式

行列式(determinant)是一种特殊的函数,以一个方阵作为输入,并输出实数。通常记作detAdet \boldsymbol{A}。定义为:

detA11=A11detA=j=1nA1j(1)1+jdetA1j(n>1)\begin{aligned} det \boldsymbol{A}_{11} &= \boldsymbol{A}_{11} \\ det \boldsymbol{A} &=\sum_{j=1}^n\boldsymbol{A}_{1j}(-1)^{1+j}det\boldsymbol{\overline{A}}_{1j} & (n>1) \end{aligned}

其中 Aij\boldsymbol{\overline{A}}_{ij}A\boldsymbol{A} 余子阵 (minor martix),即为A\boldsymbol{A} 中去除第 ii 行、第 jj 列的 (n1)×(n1)(n-1)\times(n-1) 的矩阵。

伴随矩阵

A\boldsymbol{A}n×nn\times n矩阵。乘积 Cij=(1)i+jdetAij\boldsymbol{C}_{ij}=(-1)^{i+j}det\boldsymbol{\overline{A}}_{ij} 称为 元素 Aij\boldsymbol{A}_{ij} 的代数余子式 (cofactor of Aij\boldsymbol{A}_{ij})。将Cij\boldsymbol{C}_{ij} 置于矩阵 CA\boldsymbol{C}_\boldsymbol{A} 中第 ii 行、第 jj 列的相应位置,将获得 矩阵 A\boldsymbol{A} 的代数余子式矩阵(cofactor matrix of A\boldsymbol{A}):

CA=[C11C12C1nC21C22C2nCn1Cn2Cnn]\boldsymbol{C}_\boldsymbol{A}= \left[\begin{array}{cccc} C_{11} &C_{12} &\cdots &C_{1n} \\ C_{21} &C_{22} &\cdots &C_{2n} \\ \vdots &\vdots &\ddots &\vdots \\ C_{n1} &C_{n2} &\cdots &C_{nn} \end{array} \right]

CA\boldsymbol{C}_\boldsymbol{A} 的转置矩阵,将得到 矩阵 A\boldsymbol{A} 的伴随矩阵(adjoint matrix of A\boldsymbol{A}),记作:

A=CAT\boldsymbol{A}^*=\boldsymbol{C}_\boldsymbol{A}^T

逆矩阵

  1. 只有方阵有逆矩阵。
  2. n×nn\times n矩阵 M\boldsymbol{M} 的逆也为 n×nn\times n 矩阵,表示为M1\boldsymbol{M}^{-1}
  3. 存在逆矩阵的方阵称为 可逆矩阵 (invertible matrix),不存在逆矩阵的方阵称为 奇异矩阵(singular matrix)。
  4. 可逆矩阵的逆矩阵唯一。
  5. 矩阵与它的逆矩阵相乘得到单位矩阵。

求逆矩阵公式:

A1=AdetA\boldsymbol{A}^{-1}=\frac{\boldsymbol{A}^*}{det\boldsymbol{A}}

由于我们关注的 3D 计算机图形学中所涉及的具有特殊形式的矩阵,因此提前确定出了他们的求逆矩阵公式。这样一来,上式在代码中极少被运用。


矩阵乘积的逆有如下性质:

(AB)1=B1A1(\boldsymbol{A}\boldsymbol{B})^{-1}=\boldsymbol{B}^{-1}\boldsymbol{A}^{-1}

DirectXMath 库

矩阵类型

DirectXMath 中定义 XMMATRIX 类来表示 4×44\times 4 矩阵。XMMATRIX由 4 个 XMVECTOR 实例构成,借此使用 SIMD 技术。

XMMATRIX实列可以通过:

  • 4 个行向量
  • 16 个矩阵元素
  • 含有 16 个浮点数元素的数组

来进行初始化。

DirectXMath 文档建议使用 XMFLOAT4X4 来存储类中的矩阵类型数据成员变量,并由以下加载和存储方法:

1
2
3
4
// 加载
inline XMMATRIX XM_CALLCONV XMLoadFloat4x4 (const XMFLOAT4X4 *pSource);
// 存储
inline void XM_CALLCONV XMStoreFloat4x4 (XMFLOAT4X4 *pDestination, FXMMATRIX M);

矩阵函数

1
2
3
4
5
6
7
8
9
10
11
12
// 单位矩阵 I
XMMATRIX XM_CALLCONV XMMatrixIdentity ();
// M 是单位矩阵?
bool XM_CALLCONV XMMatrixIsIdentity (FXMMATRIX M);
// A x B
XMMATRIX XM_CALLCONV XMMatrixMultiply (FXMMATRIX A, CXMMATRIX B);
// M^T
XMMATRIX XM_CALLCONV XMMatrixTranspose (FXMMATRIX M);
// (det M, det M, det M, det M)
XMVECTOR XM_CALLCONV XMMatrixDeterminant (FXMMATRIX M);
// M^-1
XMMATRIX XM_CALLCONV XMMatrixInverse (XMVECTOR* pDeterminant, FXMMATRIX M);

32 位 Windows 上的调用约定:

1
2
3
4
5
6
7
// __fastcall 将前 3 个 XMVECTOR 参数传递到寄存器中,其余参数存在栈上
typedef const XMMATRIX& FXMMATRIX;
typedef const XMMATRIX& CXMMATRIX;

// __vectorcall 将前 6 个 XMVECTOR 参数传递到寄存器中,其余参数存在栈上
typedef const XMMATRIX FXMMATRIX;
typedef const XMMATRIX& CXMMATRIX;

32 位 Windows 上的 __fastcall 调用约定中,XMMATRIX是不能传至 SSE/SSE2 寄存器的,因为寄存器这时只支持 3 个 XMVECTOR 参数传入,XMMATRIX由 4 个 XMVECTOR 构成,只能通过堆栈来引用。

构造函数是一个特例,DirectXMath 建议用户总是在构造函数中采用 CXMMATRIX 类型来获取 XMMATRIX 参数,也不要使用 XM_CALLCONV 约定注解。