✠OpenGL-3-数学基础

本文深入探讨了3D图形学中的关键概念和技术,包括齐次坐标、矩阵运算、平移、旋转、缩放等基本变换,以及透视和正射投影矩阵的构建与应用。文章还介绍了LookAt矩阵的作用和原理,并详细解析了模型-视图矩阵和投影矩阵的工作流程。

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
任何值乘以单位矩阵都不会改变。

单位矩阵也可以简单地记为一个对角线矩阵:En = diag(1,1,…,1)
根据矩阵乘法的定义,单位矩阵的重要性质为:AEn = A;EnA = A

在GLM中,调用构造函数glm::mat4 m(1.0f);以在变量m中生成单位矩阵。

②转置矩阵:
矩阵转置的计算是通过交换矩阵的行与列完成的。转置,就是旋转置换的意思;给定一个mxn的矩阵,则A的转置就是nxm的矩阵,用AT表示。例如:

转置矩阵特性:
1、(A) = A
2、(A+B) = A + B
3、对任意数r,(rA) = rA
4、(AB) = BA

GLSL库和GLM库都有转置函数,分别是transpose(mat4)glm::transpose(mat4)

➂逆矩阵
一个4×4矩阵的逆矩阵是另一个4×4矩阵,用M-1表示。

在矩阵乘法中有如下性质:
M×M-1 = M-1×M = 单位矩阵 E
AB = BA = E,则 A 是可逆的,BA 的逆矩阵(B=A-1)。
若A可逆,则A-1亦可逆,且:(A-1)-1 = A
若A可逆,则AT亦可逆,且:(AT)-1=(A-1)T
若A、B为同阶方阵且均可逆,则AB亦可逆,且:(AB)-1=B-1A-1

GLSL和GLM都提供了mat4.inverse()函数完成矩阵的逆矩阵运算。

➊矩阵加法:

GLSL 和 GLM 都支持使用重载后的加法“+”运算符,进行矩阵加法。

➋矩阵乘法:

矩阵相乘也经常叫作合并
我们需要经常将相同的一系列矩阵变换应用到场景中的每个点上。通过预先一次计算好这些矩阵的合并,就可以成倍减少总的矩阵运算量。

GLSL 和 GLM 都支持使用重载后的乘法“*”运算符,进行矩阵乘法。

点与矩阵相乘,得到新点:

我们用齐次坐标将点(X, Y, Z)表示为列数为1的矩阵。
注意,矩阵乘法不满足【交换律】。(很容易证明交换律不成立)

矩阵乘法满足【结合律】:(很容易证明结合律成立)
Now Point = M1×(M2×(M3×Point)) == (M1×M2×M3)×Point( = M123合并×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中有一些函数是用于构建与点相乘的平移矩阵的。相关操作有:

  • mat4 glm::translate(mat4 const& m, vec3 const& v) 通过3元素向量,构建4×4平移变换矩阵;
  • mat4 × vec4 // 4×4矩阵 × 4元素向量 => 新4元素向量。

一般是用单位矩阵来使3元素平移向量生成平移变换矩阵:
glm::mat4 m = glm::translate(glm::mat4(1.0f), glm::vec3(x,y,z));
结果如下:
1 0 0 x
0 1 0 y
0 0 1 z
0 0 0 1 (刚好满足平移变换矩阵的格式)
注:对于vec3 类型,要用它可以与乘以的 4× 4 矩阵兼容,需要将其转换为 vec4 类型,这个转换是用 vec4(vec3,1.0)完成的。

➋缩放矩阵
缩放矩阵用于改变物体的大小或者将点向原点相反方向移动。虽然缩放点这个操作乍一看有点奇怪,不过 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) XSxYSyZSz1 = Sx0000Sy0000Sz00001 × XYZ1
GLM中有一些函数是用于构建与点相乘的缩放矩阵的。相关操作有:

  • glm::scale(x, y, z) 构建缩放(x, y, z)的矩阵;
  • mat4 × vec4

缩放还可以用来 切换坐标系
例如,可以用缩放来在给定右手坐标系的情况下确定左手坐标。

从上图可以看到通过反转Z坐标就可以从右手坐标切换为左手坐标。因此,用来切换坐标系的缩放矩阵变换是:
[ 1 0 0 0 0 1 0 0 0 0 − 1 0 0 0 0 1 ] \left[ \begin{array} { l l l l } { 1 } & { 0 } & { 0 } & { 0 } \\ { 0 } & { 1 } & { 0 } & { 0 } \\ { 0 } & { 0 } & { -1 } & { 0 } \\ { 0 } & { 0 } & { 0 } & { 1 } \end{array} \right] 1000010000100001
➌旋转矩阵
旋转会稍微复杂一些,因为在 3D 空间中旋转物体需要指定旋转轴和旋转的角度或弧度。

数学家莱昂哈德· 欧拉表明,围绕任何轴的旋转都可以表示为绕 X、Y、Z 轴旋转的组合。围绕这 3 个轴的旋转角度被称为欧拉角。 这个被称为欧拉定理的发现,对我们很有用,因为对于每个坐标轴的旋转可以用矩阵变换来表示。

下面展示了3种旋转变换,即绕X、Y和Z轴旋转。

ⓐ绕X轴旋转θ度:
( X ′ Y ′ Z ′ 1 ) = [ 1 0 0 0 0 c o s θ − s i n θ 0 0 s i n θ c o s θ 0 0 0 0 1 ] × ( X Y Z 1 ) \left( \begin{array} { l } { X' } \\ { Y' } \\ { Z' } \\ { 1 } \end{array} \right) = \left[ \begin{array} { l l l l } { 1 } & { 0 } & { 0 } & { 0 } \\ { 0 } & { cosθ } & { -sinθ } & { 0 } \\ { 0 } & { sinθ } & { cosθ } & { 0 } \\ { 0 } & { 0 } & { 0 } & { 1 } \end{array} \right] \times \left( \begin{array} { l } { X } \\ { Y } \\ { Z } \\ { 1 } \end{array} \right) XYZ1 = 1000

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

itzyjr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值