✠OpenGL-3-数学基础
Posted itzyjr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了✠OpenGL-3-数学基础相关的知识,希望对你有一定的参考价值。
目录
3D坐标系统
3D图形学中几乎每个方面、每种效果——移动、缩放、透视、纹理、光照、阴影等都在很大程度上以数学方式实现。
在OpenGL中的坐标系大体是右手坐标系。
点
3D空间中的点可以通过使用形如(2, 8, -3)的符号,列出X、Y、Z的值来表示。不过,如果用齐次坐标
来表示点会更有用。在每个点的齐次坐标有4个值。即(X, Y, Z, W),其中W总是非零值,通常为1。因此我们会将之前的点表示为(2, 8, -3, 1)。齐次坐标将会使我们的图形学计算更高效。
用来存储齐次3D坐标的GLSL数据类型是vec4。GLM库包含适合在C++/OpenGL应用中创建和存储3元和4元(齐次)点的类,分别叫作vec3和vec4。
矩阵(单位矩阵、转置矩阵、逆矩阵;矩阵加法和乘法)
[
A
00
A
01
A
02
A
03
A
10
A
11
A
12
A
13
A
20
A
21
A
22
A
23
A
30
A
31
A
32
A
33
]
\\left[ \\begin{matrix} A_{00} & A_{01} & A_{02} & A_{03} \\\\ A_{10} & A_{11} & A_{12} & A_{13} \\\\ A_{20} & A_{21} & A_{22} & A_{23} \\\\ A_{30} & A_{31} & A_{32} & A_{33} \\end{matrix} \\right]
⎣⎢⎢⎡A00A10A20A30A01A11A21A31A02A12A22A32A03A13A23A33⎦⎥⎥⎤
GLSL语言中的mat4数据类型用来存储4×4矩阵。同样,GLM库中有mat4类用以实例化并存储4×4矩阵。
①单位矩阵:
一条对角线的值为1,其余值全为0。
[
1
0
0
0
0
1
0
0
0
0
1
0
0
0
0
1
]
\\left[ \\begin{matrix} 1& 0& 0& 0 \\\\ 0& 1& 0& 0 \\\\ 0& 0& 1& 0 \\\\ 0& 0& 0& 1 \\end{matrix} \\right]
⎣⎢⎢⎡1000010000100001⎦⎥⎥⎤
任何值乘以单位矩阵
都不会改变。
在GLM中,调用构造函数glm::mat4 m(1.0f)以在变量m中生成单位矩阵。
②转置矩阵:
矩阵转置的计算是通过交换矩阵的行与列完成的。例如:
GLSL库和GLM库都有转置函数,分别是transpose(mat4)
和glm::transpose(mat4)
。
➂逆矩阵
一个4×4矩阵的逆矩阵是另一个4×4矩阵,用M-1表示。在矩阵乘法中有如下性质:
M×M-1 = M-1×M = 单位矩阵 E
若 AB = BA = E,则 A 是可逆的,B 是 A 的逆矩阵。
GLSL和GLM都提供了mat4.inverse()
函数完成矩阵的逆矩阵运算。
➊矩阵加法:
在GLSL中,+运算符在mat4上进行了重载,以支持矩阵加法。
➋矩阵乘法:
矩阵相乘也经常叫作合并
。
我们需要经常将相同的一系列矩阵变换应用到场景中的每个点上。通过预先一次计算好这些矩阵的合并,就可以成倍减少总的矩阵运算量。
GLSL 和 GLM 都支持使用重载后的*运算符进行矩阵乘法。
点与矩阵相乘,从右向左,得到点:
我们用齐次坐标将点(X, Y, Z)表示为列数为1的矩阵。
注意,矩阵乘法不满足【交换律】。(很容易证明交换律不成立)
矩阵乘法满足【结合律】:(很容易证明结合律成立)
Now Point = M1×(M2×(M3×Point)) == (M1×M2×M3)×Point
变换矩阵(平移、缩放、旋转、投影[透视/正射]、LookAt)
变换矩阵的重要特性之一就是它们都是 4× 4 矩阵。这是因为我们决定使用齐次坐标系。否则,各变换矩阵可能会有不同的维度并且无法相乘。正如我们所见,确保变换矩阵大小相同并不只是为了方便,同时让它们可以任意组合,进行预先计算变换矩阵以提升性能。
➊平移矩阵
平移矩阵用于将物体从一个位置移至另一位置。
下面展示了平移矩阵和它与齐次坐标点相乘的效果——平移矩阵变换:
(
X
+
T
x
Y
+
T
y
Z
+
T
z
1
)
=
[
1
0
0
T
x
0
1
0
T
y
0
0
1
T
z
0
0
0
1
]
×
(
X
Y
Z
1
)
\\left( \\begin{array} { l } { X+T_x } \\\\ { Y+T_y } \\\\ { Z+T_z } \\\\ { 1 } \\end{array} \\right) = \\left[ \\begin{array} { l l l l } { 1 } & { 0 } & { 0 } & { T_x } \\\\ { 0 } & { 1 } & { 0 } & { T_y } \\\\ { 0 } & { 0 } & { 1 } & { T_z } \\\\ { 0 } & { 0 } & { 0 } & { 1 } \\end{array} \\right] \\times \\left( \\begin{array} { l } { X } \\\\ { Y } \\\\ { Z } \\\\ { 1 } \\end{array} \\right)
⎝⎜⎜⎛X+TxY+TyZ+Tz1⎠⎟⎟⎞=⎣⎢⎢⎡100001000010TxTyTz1⎦⎥⎥⎤×⎝⎜⎜⎛XYZ1⎠⎟⎟⎞
注意,这个乘法是从右向左相乘。
()是代表向量vector,[]是代表矩阵matrix
平移矩阵变换的结果:
点(X, Y, Z)平移到了位置(X+Tx, Y+Ty, Z+Tz)
例如,将一组点向上沿Y轴正方向移动5个单位,可以通过给一个单位矩阵的Ty位置放入5来构建平移矩阵。之后只需将想要移动的点与矩阵相乘就可以了。
GLM中有一些函数是用于构建与点相乘的平移矩阵的。相关操作有:
- glm::translate(x, y, z) 构建平移(x, y, z)的矩阵;
- mat4 × vec4 // 4×4矩阵 × 4元素向量 => 新4元素向量
➋缩放矩阵
缩放矩阵用于改变物体的大小或者将点向原点相反方向移动。虽然缩放点这个操作乍一看有点奇怪,不过 OpenGL 中的物体都是用一组或多组的点定义的。因此,缩放物体涉及缩放它的点的集合。
下面展示了缩放矩阵的形式和当它与齐次坐标点相乘的效果——经过缩放值修改后的新点。
(
X
∗
S
x
Y
∗
S
y
Z
∗
S
z
1
)
=
[
S
x
0
0
0
0
S
y
0
0
0
0
S
z
0
0
0
0
1
]
×
(
X
Y
Z
1
)
\\left( \\begin{array} { l } { X*S_x } \\\\ { Y*S_y } \\\\ { Z*S_z } \\\\ { 1 } \\end{array} \\right) = \\left[ \\begin{array} { l l l l } { S_x } & { 0 } & { 0 } & { 0 } \\\\ { 0 } & { S_y } & { 0 } & { 0 } \\\\ { 0 } & { 0 } & { S_z } & { 0 } \\\\ { 0 } & { 0 } & { 0 } & { 1 } \\end{array} \\right] \\times \\left( \\begin{array} { l } { X } \\\\ { Y } \\\\ { Z } \\\\ { 1 } \\end{array} \\right)
⎝⎜⎜⎛X∗SxY∗SyZ∗S✠OpenGL-2-图像管线