6 - 变换
前面我们将小矩形贴上了纹理,接下来我们将通过 变换(Transformation) 的方式,让它动起来。有关变换的理论知识有很多,前置知识就有向量、矩阵什么的,详见在GAMES101中写的文章。这里直接跳到实践部分。
实践
配置GLM
OpenGL没有自带的数学库,因此得自己搞或者上网找现成的,在这里可以找到一个专门为OpenGL量身定制的数学库 GLM。
下载好文件后,只需将glm/glm
文件夹复制到includes
文件夹即可:
然后包括这些头文件,我们需要的大多数GLM功能就在其中:
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
可以写一段测试代码:
glm::vec4 vec(1.0f, 0.0f, 0.0f, 1.0f);
// 我用的是glm0.9.9版本,默认会将矩阵初始化为0矩阵,而不是单位矩阵
glm::mat4 trans = glm::mat4(1.0f);
// 如果是glm0.9.9以下的,应该是这一行
// glm::mat4 trans;
trans = glm::translate(trans, glm::vec3(1.0f, 1.0f, 0.0f));
vec = trans * vec;
std::cout << vec.x << vec.y << vec.z << std::endl;
这段代码把一个向量(1, 0, 0)位移(1, 1, 0)个单位。第一行告诉我们如何声明一个向量(这里使用齐次坐标,因此是4D)。然后创建了一个单位矩阵trans
用于接下来的变换操作,通过glm::translate(mat4, vec3)
将单位矩阵和一个位移向量组合成该位移向量的变换矩阵,并对刚开始的向量进行相乘,最终得到结果210.
变换小矩形
接下来可以对画出来的小矩形进行变换,例如对其先缩放0.5倍,然后逆时针旋转90°。
首先创建变换矩阵:
glm::mat4 trans = glm::mat4(1.0f);
// 先缩放0.5倍,然后在原点绕z轴逆时针旋转90°(注意弧度制)
trans = glm::rotate(trans, glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0));
trans = glm::scale(trans, glm::vec3(0.5, 0.5, 0.5));
其中,glm::rotate(trans, angle, axis)
函数将trans
矩阵右乘一个旋转angle
度(注意弧度制),绕axis
旋转的旋转矩阵;glm::scale(trans, vec3)
将trans
右乘一个按照vec3
缩放的缩放矩阵。并且注意到,由于OpenGL采用的是列向量,矩阵是从右往左乘的,因此是先缩放后旋转。
得到的效果如图:
接下来,尝试结合glfwGetTime()
函数让该小矩形动起来:
// in rander loop
// ...
// ----------------矩阵变换---------------
glm::mat4 trans = glm::mat4(1.0f);
trans = glm::scale(trans, glm::vec3(0.5, 0.5, 0.5));
trans = glm::rotate(trans, (float)(glfwGetTime()), glm::vec3(0.0, 0.0, 1.0));
// --------------------------------------
// 设置矩阵变换的transform变量
unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
效果如下:
十分有趣。
参考资料
- 变换 - LearnOpenGL CN (learnopengl-cn.github.io)