图形的变换

来源:互联网 发布:互联网运营工资 知乎 编辑:程序博客网 时间:2024/05/22 17:36

在了解矩阵的变换之后,我们就可以开始对图形进行变换。这里使用的变换图形是之前绘制出来的笑脸箱子。欢迎光临我的个人网站Orient一起讨论学习。这里是我的GitHub,如果您喜欢,不妨点个 star。☺

数学库包

首先我们需要引入专门为OpenGL量身定做的数学库——GLM(OpenGL Mathematics)
我们可以从它的网站上下载。

GLM的网站可能需要通过VPN访问,如果你无法访问,你可以点击这里进行下载。如果你使用的是Visual Studio 2017 ,那么在你搭建完开发环境后,你可以直接引入GLM的相关头文件

我们需要引入以下3个头文件:

#include <glm/glm.hpp>#include <glm/gtc/matrix_transform.hpp>#include <glm/gtc/type_ptr.hpp>

变换

uniform

在变换之前,我们需要修改顶点着色器,让其接收一个 mat4uniform 变量,然后在用矩阵 uniform 乘以位置向量:

#version 430 corelayout (location = 0) in vec3 aPos;layout (location = 1) in vec2 aTexCoord;out vec2 TexCoord;uniform mat4 transform;void main(){    gl_Position = transform * vec4(aPos, 1.0f);    TexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y);}

变换矩阵

首先我们把箱子逆时针旋转90度(沿着Z轴旋转),然后缩放0.5倍。我们需要创建变换矩阵:

glm::mat4 transfromtransform = glm::rotate(transform, glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0));transform = glm::scal(transform, glm::vec3(0.5, 0.5, 0.5));

可以看到,变换顺序和程序编写顺序刚好相反。在程序中,我们先写出旋转变换,然后再写缩放变换

glm::rotate 函数是旋转函数。GLM希望旋转的角度是弧度制,所以使用了 glm::radians 对角度进行转换。同时我们的纹理是在 XY 平面上,所以我们把它绕着Z轴
(0.0, 0.0, 1.0) 进行旋转。
glm::scal 函数是缩放函数,我们需要将纹理图像对应的轴缩放 (0.5, 0.5, 0.5) 倍。

把变换矩阵传递给着色器

unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));

首先用 glGetUniformLocation 函数查询了 uniform 变量地址。

然后用 glUniformMatrix4fv 函数把矩阵数据发送给着色器。
第一个参数是 uniform 的位置值;
第二个参数告诉OpenGL发送的矩阵个数,这里是1;
第三个参数确定是否进行矩阵置换(交换行和列)。GLM中不需要,所以设置为 GL_FALSE;
第四个参数是矩阵数据,但GLM并不是把矩阵存储为OpenGL期望接受的格式,因此这里用 glm::value_ptr 函数变换数据。

以上完成了纹理图像的缩放旋转

接下来我们让纹理图像随着时间变换而不断旋转

我们只需要将变换矩阵更改成如下形式即可:

glm::mat4 transform;transform = glm::translate(transform, glm::vec3(0.5f, -0.5f, 0.0f));transform = glm::rotate(transform, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));

glm::translate 函数是位移函数,将纹理图像位移了 (0.5, -0.5, 0.0) 个单位,将纹理图像位移到了屏幕的右下角。

我们把旋转函数的第二个参数改成了 glfwGetTime(),因此纹理图像旋转的弧度是随着运行时间的增加而不断增加的。

运行效果如下:


动图加载可能有点慢

本文的代码可在这里找到,如果对您有所帮助,不妨点个赞。☺

原创粉丝点击