【OpenGL】学习笔记#3

唉,虽然学会了,但是懒得做笔记呀。俗话说好记性不如烂笔头,防止遗忘我还是记一记吧。

一、矩阵

众所周知,三弟3D图形学中很重要的就是线性代数,我们进行各种变换的时候就要用到神奇的矩阵。

(不禁想吐槽一句,这个神奇的东西到底是怎么想出来的。。)

相信矩阵乘法大家都了解,下面讲几种特殊的矩阵。

1.平移矩阵(Translate Matrix)

在讲矩阵之前,先说一个东西:齐次坐标。

为了区分矢量和标量,我们用第四维w来表示,v(x,y,z,w) ,则w=1 => v是空间中的位置,w=0 => v是向量。

那么我们想要在x轴上移动位置v(10,10,10,1),那么相应的平移矩阵就是

1 ,0 ,0 ,10

0 ,1 ,0 ,0

0 ,0 ,1 ,0

0 ,0 ,0 ,1

将它乘上我们的v,根据矩阵乘法得到v'(20,10,10,1),显然是正确的。

如果v是(-1,0,0,0)呢?(代表x轴负方向),根据计算得到(-1,0,0,0),显然是正确的,因为移动方向没有意义,帅呆了!

定义一个平移矩阵:

glm::mat4 myMatrix = glm::translate(glm::mat4(), glm::vec3(10.0f, 0.0f, 0.0f));

把位置和矩阵相乘:

glm::vec4 myVector(10.0f, 10.0f, 10.0f, 0.0f);
glm::vec4 transformedVector = myMatrix * myVector; // guess the result

相乘的代码是一样的,下文不表。

2.单位矩阵(The Identity Matrix)

1 ,0 ,0 ,0

0 ,1 ,0 ,0

0 ,0 ,1 ,0

0 ,0 ,0 ,1

它就相当于1,任何数乘上1不会改变,单位矩阵乘上单位矩阵也是一样。

代码:

glm::mat4 myIdentityMatrix = glm::mat4(1.0f);

3.缩放矩阵(Scaling matrices)

x ,0 ,0 ,0

0 ,y ,0 ,0

0 ,0 ,z ,0

0 ,0 ,0 ,1

xyz就是缩放的倍数,多么优美的矩阵。

代码:

glm::mat4 myScalingMatrix = glm::scale(2.0f, 2.0f ,2.0f);

4.旋转矩阵(Rotation matrices)

很复杂的东西,贴代码:

// RotationAngle is in radians
x = RotationAxis.x * sin(RotationAngle / 2)
y = RotationAxis.y * sin(RotationAngle / 2)
z = RotationAxis.z * sin(RotationAngle / 2)
w = cos(RotationAngle / 2)

代码:

glm::vec3 myRotationAxis( ??, ??, ??);
glm::rotate( angle_in_degrees, myRotationAxis );

这里不涉及到矩阵,OpenGL已经封装好了。(如此贴心!)

介绍完了矩阵们,接下来要用到他们变换我们的3D世界了。

变换大致是这样的流程:

模型坐标系--×模型矩阵-->世界坐标系--×相机矩阵-->相机坐标系--×透视矩阵-->屏幕坐标系

模型坐标系和世界坐标系:假定(0,0,0,1)是模型的中心点,将它乘上一个平移矩阵,此时它的位置就不是(0,0,0,1),而是另一个位置,此时它就处于世界坐标系。(细品)

相机坐标系:把相机往一个位置移动似乎不好解决(仔细想,因为所有的变换都是为了让物体在屏幕上以一个真实的方式呈现,我们不择手段),所以我们移动世界,把一切顶点移动,幸运的是OpenGL已经为我们实现了!

屏幕坐标系:通过透视变换,我们把3D变成了2D(画家:我恨数学!)!具体实现比较复杂,不细说,但是原理也是通过乘上一个透视变换的矩阵,这个矩阵OpenGL也为我们提供了!(欢呼!)

下面是代码实现:

模型矩阵:(我们把它放到世界原点,所以就用单位矩阵作为模型矩阵)

glm::mat4 Model      = glm::mat4(1.0f);

相机矩阵:(使用lookAt函数)

glm::mat4 View       = glm::lookAt(
                                glm::vec3(4,3,-3), // Camera is at (4,3,-3), in World Space
                                glm::vec3(0,0,0), // and looks at the origin
                                glm::vec3(0,1,0)  // Head is up (set to 0,-1,0 to look upside-down)
                           );

第一个参数是相机位置(世界坐标系),第二个是相机观察的位置,第三个是向上的方向(用于计算一个交叉积,一定要填对喔!)。

透视矩阵:

glm::mat4 Projection = glm::perspective(glm::radians(45.0f), 4.0f / 3.0f, 0.1f, 100.0f);

第一个参数代表Fov,视角大小,第二个代表屏幕宽高比,第三个代表近裁剪面(近于这个值的物体将被裁剪,不显示),第四个代表远裁剪面(远于这个值的物体将被裁剪,不显示)。

最后,把这三个矩阵相乘,即可得到顶点们的变换了。

glm::mat4 MVP        = Projection * View * Model;

注意顺序!

原文地址:https://www.cnblogs.com/dudujerry/p/13542357.html