OpenGL中的变换
1. 矩阵变换
在opengl中矩阵变换使用的为齐次坐标;使用齐次坐标有几点好处:它允许我们在3D向量上进行位移,同时也方便使用透视投影操作。本篇文章主要偏向于实现,不深究理论的知识。
1.1 缩放
为向量(x,y,z)定义一个缩放矩阵
1.2 平移
为向量(x,y,z)定义一个平移矩阵
1.3 旋转
旋转过程涉及到弧度与角度的转化
弧度转角度
:角度 = 弧度 * (180.0f / PI)角度转弧度
:弧度 = 角度 * (PI / 180.0f)
opengl中使用的是角度制
为向量(x,y,z)定义一个旋转矩阵
1.4 矩阵组合
假设我们有一个顶点(x, y, z),我们希望将其缩放2倍,然后位移(1, 2, 3)个单位。变换矩阵可以描述为:
注意:最右边的矩阵是第一个与向量相乘的,所以应该从右向左读这个乘法,即先缩放后平移。
2. 案例实现
在OpenGL中使用矩阵变化,首先需要包含矩阵库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);//坐标(1.0f, 0.0f, 0.0f)
// 下面是矩阵初始化的一个例子,如果使用的是0.9.9及以上版本
// 下面这行代码就需要改为:
// glm::mat4 trans = glm::mat4(1.0f)
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;
若是输出结果为(2,1,0)说明配置成功
在做变换之前需要修改下顶点着色器,在着色器中添加与变换矩阵相关的内容
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 TexCoord;
uniform mat4 transform;//GLSL中的mat4类型
void main()
{
//修改顶点着色器让其接收一个mat4的uniform变量,然后再用矩阵uniform乘以位置向量
gl_Position = transform * vec4(aPos, 1.0);
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
其余的部分代码保持不变,仅需要修改渲染循环中的代码:
[transformLoc 矩阵一系列变换....]
unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
- 第一个参数你现在应该很熟悉了,它是uniform的位置值。
- 第二个参数告诉OpenGL我们将要发送多少个矩阵,这里是1。
- 第三个参数询问我们是否希望对我们的矩阵进行转置(Transpose),也就是说交换我们矩阵的行和列。OpenGL开发者通常使用一种内部矩阵布局,叫做列主序(Column-major Ordering)布局。GLM的默认布局就是列主序,所以并不需要转置矩阵,我们填GL_FALSE。
- 最后一个参数是真正的矩阵数据,但是GLM并不是把它们的矩阵储存为OpenGL所希望接受的那种,因此我们要先用GLM的自带的函数value_ptr来变换这些数据