0 前言
本节笔记对应的内容 变换
在这一节,我们将会了解有关材质的内容
尽管我们现在已经知道了如何创建一个物体、着色、加入纹理,给它们一些细节的表现,但因为它们都还是静态的物体,仍不会动
所以这一节,我们尝试用线性代数的知识让它动起来
这章中关于向量,矩阵以及相关的运算就不在这里赘述了,可以去看
3Blue1Brown的线性代数的本质系列视频——在直观层面非常好的展示了线性代数,比起直接上数字的矩阵学习可能更形象,理解也更好。
或参考本博客中GAMES101-学习笔记1-MVP变换部分
1 实践
现在我们已经解释了变换背后的所有理论,是时候将这些知识利用起来了。OpenGL没有自带任何的矩阵和向量知识,所以我们必须定义自己的数学类和函数。在教程中我们更希望抽象所有的数学细节,使用已经做好了的数学库。幸运的是,有个易于使用,专门为OpenGL量身定做的数学库,那就是GLM。
GLM
GLM是OpenGL Mathematics的缩写,它是一个只有头文件的库,也就是说我们只需包含对应的头文件就行了,不用链接和编译。
我们同样还是通过vcpkg库管理工具下载,下载完成后配置工程对应的CMakeLists文件。下载时注意vcpkg的版本。我们使用的是vcpkg是2021-01-13版,对应下载的glm版本为0.9.9.8
GLM库从0.9.9版本起,默认会将矩阵类型初始化为一个零矩阵(所有元素均为0),而不是单位矩阵(对角元素为1,其它元素为0)。如果你使用的是0.9.9或0.9.9以上的版本,你需要将所有的矩阵初始化改为 glm::mat4 mat = glm::mat4(1.0f)。如果你想与本教程的代码保持一致,请使用低于0.9.9版本的GLM,或者改用上述代码初始化所有的矩阵。
代码实现
我们要在着色器中应用变换矩阵(高效),所以首先在着色器代码中新开uniform槽位,便于矩阵的传入,修改顶点着色器让其接收一个mat4的uniform变量,然后再用矩阵uniform乘以位置向量:
#version 330 core
layout(location = 0) in vec3 aPos; // 位置变量的属性位置值为 0
layout(location = 1) in vec3 aColor; // 颜色变量的属性位置值为 1
layout(location = 2) in vec2 aTexCoord; // uv变量的属性位置值为 2
out vec4 vertexColor;
out vec2 TexCoord;
uniform mat4 transform;
void main(){
gl_Position = transform * vec4(aPos.x, aPos.y, aPos.z, 1.0);
vertexColor = vec4(aColor,1.0);
TexCoord = aTexCoord;
}
在渲染循环使用shader的部分添加如下代码:
glUniformMatrix4fv(glGetUniformLocation(testShader->ID, "transform"), 1, GL_FALSE, glm::value_ptr(trans));
我们首先查询uniform变量的地址,然后用有Matrix4fv后缀的glUniform函数把矩阵数据发送给着色器。
- 第一个参数你现在应该很熟悉了,它是uniform的位置值。
- 第二个参数告诉OpenGL我们将要发送多少个矩阵,这里是1。
- 第三个参数询问我们我们是否希望对我们的矩阵进行置换(Transpose),也就是说交换我们矩阵的行和列。OpenGL开发者通常使用一种内部矩阵布局,叫做列主序(Column-major Ordering)布局。GLM的默认布局就是列主序,所以并不需要置换矩阵,我们填GL_FALSE。
- 最后一个参数是真正的矩阵数据,但是GLM并不是把它们的矩阵储存为OpenGL所希望接受的那种,因此我们要先用GLM的自带的函数value_ptr来变换这些数据。
下面来创建变换矩阵,对变换来说,是先缩放,再旋转,再位移。
Mt: transpose 位移
Mr: rotate 旋转
Ms: scale 缩放
V: 顶点位置(列主序)
V = (Mt * Mr * Ms) * V
我们需要算出变换矩阵的话,需要按照位移→旋转→缩放的顺序调用glm的方法来乘起来。实际的变换顺序应该与阅读顺序相反:尽管在代码中我们先位移再旋转,实际的变换却是先应用旋转再是位移的。
//计算变换矩阵
glm::mat4 trans;
trans = glm::translate(trans, glm::vec3(1.0f, 0.0f, 0.0f));
trans = glm::rotate(trans, glm::radians(45.0f), glm::vec3(0.0, 0.0, 1.0));
trans = glm::scale(trans, glm::vec3(0.5, 0.5, 0.5));
「如果这篇文章对你有用,请随意打赏」
如果这篇文章对你有用,请随意打赏
使用微信扫描二维码完成支付

comments powered by Disqus