美文网首页
七、变换

七、变换

作者: 凉夜lrs | 来源:发表于2020-10-26 18:27 被阅读0次

    尽管我们现在已经知道了如何创建一个物体、着色、加入纹理,给它们一些细节的表现,但因为它们都还是静态的物体,无法实现旋转、平移和缩放。可以尝试着在每一帧改变物体的顶点并且重配置缓冲区从而使它们移动,但这太繁琐了,而且会消耗很多的处理时间。使用(多个)矩阵(Matrix)对象可以更好的变换(Transform)一个物体是一个更好的解决方案。

    向量和矩阵的运算公式和数学性质可以看这里,写的很详细。https://www.khanacademy.org/math/algebra2/algebra-matrices

    GLM

    OpenGL可编程渲染管线没有自带任何的矩阵和向量运算(glTranslatef,glRotatef这些是固定管线的内容,GLAD core模式下无法使用)。想要抽象所有的数学细节,需要使用已经做好了的数学库,GLM就是一个专门为OpenGL量身定做的数学库,下载可以自行百度。

    GLM是OpenGL Mathematics的缩写,它是一个只有头文件的库,也就是说只需包含对应的头文件就行了,不用链接和编译。需要的GLM的大多数功能都可以从下面这3个头文件中找到:

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

    GLM的旋转、平移和缩放:

    glm::mat4 trans = glm::mat4(1.0f);
    trans = glm::rotate(trans, glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));//角度转弧度
    trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f));
    trans = glm::scale(trans, glm::vec3(0.5, 0.5, 0.5));
    

    GLM库从0.9.9版本起,默认会将矩阵类型初始化为一个零矩阵(所有元素均为0),而不是单位矩阵(对角元素为1,其它元素为0),所以定义时最好先初始化所有的矩阵。

    在每个轴都缩放到0.5倍,然后平移,然后沿z轴旋转90度。GLM希望它的角度是弧度制的(Radian),所以使用glm::radians将角度转化为弧度。显示图形是在XY平面上的,所以需要把它绕着z轴旋转(也可以试试其他轴的效果)。因为我们把这个矩阵传递给了GLM的每个函数,GLM会自动将矩阵相乘,返回的结果是一个包括了多个变换的变换矩阵。

    尽管在代码中先旋转再位移再缩放,实际的变换却是正好相反的,是先缩放再位移再旋转。

    把矩阵传递给着色器

    #version 330 core
    layout (location = 0) in vec3 aPox;
    
    uniform mat4 transform;
    void main()
    {
        gl_Position = transform * vec4(aPox, 1.0);
    }
    

    GLSL里有一个mat4类型。让其接收一个mat4的uniform变量,然后再用矩阵uniform乘以位置向量。

    glUniformMatrix4fv(glGetUniformLocation(shader.shaderProgramId, "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来变换这些数据。

    PS

    旋转和位移这里很有意思,交换顺序的结果很哲学:

    If we would first apply rotations then they'd resolve around the rotation origin (0,0,0), but
    since the container is first translated, its rotation origin is no longer (0,0,0) making it
    looks as if its circling around the origin of the scene.

    相关文章

      网友评论

          本文标题:七、变换

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