图形的变换

作者: Orient_ZY | 来源:发表于2017-07-19 16:03 被阅读93次

    在了解矩阵的变换之后,我们就可以开始对图形进行变换。这里使用的变换图形是之前绘制出来的笑脸箱子。欢迎光临我的个人网站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 core
    layout (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 transfrom
    transform = 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(),因此纹理图像旋转的弧度是随着运行时间的增加而不断增加的。

    运行效果如下:


    动图加载可能有点慢动图加载可能有点慢

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

    相关文章

      网友评论

        本文标题:图形的变换

        本文链接:https://www.haomeiwen.com/subject/ygulkxtx.html