坐标系统

作者: Orient_ZY | 来源:发表于2017-08-11 16:45 被阅读35次

    最近在学习OpenGL,把学习的一些过程写在这里,希望与大家共同分享讨论。欢迎光临我的个人网站Orient.ren一起讨论学习。这里是我的GitHub果您喜欢,不妨点个赞?☺

    坐标系统分为五大类:

    局部空间(Local Space)或被称为物体空间(Object Space)

    指的是单个物体的坐标系统。

    世界空间(World Space)

    指多个物体同时放在一个世界的坐标系统。物体坐标从局部空间变换到世界空间是由模型矩阵(Model Matrix)实现的。

    模型矩阵:是一种变幻矩阵,它通过对物体进行位移、缩放、旋转来将它放置在预期的位置或朝向。

    观察空间(View Space)或被称为视觉空间(Eye Space)、摄像机空间(Camera Space)

    将世界空间坐标转化为用户视野前方的坐标而产生的结果。也就是从摄像机视角所观察到的空间。通常由一系列的唯一和旋转的组合来完成。

    这些组合被存储在一个观察矩阵(View Matrix)里,它被用来将世界坐标变幻到观察空间坐标。

    裁剪空间(Clip Space)

    将规定范围之外的物体裁剪掉(不可视化)。它由投影矩阵(Projection Matrix)实现。

    投影分为正射投影透视投影

    创建正射投影矩阵可以用GLM的内置函数glm::ortho:

    /*p1、p2:指定了平截头体的左右坐标,
     *p3、p4:制订了平截头体的底部和顶部,
     *p5、p6:定义了近平面和远平面的距离
     */
    glm::ortho(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f);
    

    创建透视投影矩阵可以用以下函数创建:

    /*p1:定义了fov(视野:`Field of View`)的值,并且设置了观察空间的大小,一般为了真实效果,设置为45.0f,
     *p2:设置宽高比,由视口宽除以高所得,
     *p3、p4:设置了平截头体的近、远平面距离,通常按以下值设置。
     */
    glm::nat4 proj = glm::perspective(glm::radians(45.0f), (float)width/(float)height, 0.1f, 100.0f);
    

    屏幕空间(Screen Space)

    屏幕空间也就是我们在屏幕上所能看见的一个窗口空间

    一个物体的顶点坐标起始于局部空间(Local Space),在这里被称为局部坐标(Local Coordinate),之后会变味世界坐标(World Coordinate),观察坐标(View Coordinate),裁剪坐标(Clip Coordinate),在最后以屏幕坐标(Screen Coordinate)的形式结束

    一个顶点坐标将会根据以下过程变换到裁剪坐标:

    V(clip) = M(projection) · M(view) · M(model) · V(local)

    最后顶点应该被赋值到顶点着色器中的gl_Position, OpenGL将会自动进行透视除法裁剪将其变化到标准化设备坐标,然后通过glViewPort内部的参数来将标准化设备坐标映射到屏幕坐标。

    3D

    模型矩阵

    创建一个包含位移、缩放与旋转的模型矩阵,将物体变换到全局的世界空间,下面这个模型矩阵使得物体绕x轴旋转,使它看起来像放在地上一样:

    glm::mat4 model;
    model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0f, 0.0f, 0.0f));
    

    观察矩阵

    创建一个观察矩阵,将物体在场景里稍微后移,以使得物体变成可见的:

    glm::mat4 view
    view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
    

    投影矩阵

    最后定义一个投影矩阵,在这里使用透视投影:

    glm::mat4 projection
    projection = glm::perspective(glm::radians(45.0f), screenWidth / screenHeight, 0.1f, 100.0f);
    

    申明uniform变换矩阵

    创建变换矩阵后,将它们传入着色器。首先申明一个uniform变换矩阵然后将它乘以顶点坐标:

    #version 410 core
    layout (location = 0) in vec3 aPos;
    ...
    uniform mat4 model;
    uniform mat4 view;
    uniform mat4 projection;
    
    void main()
    {
        gl_Position = projection * view * model * vec4(aPos, 1.0);
    }
    

    然后将矩阵传入着色器(通常在每次的渲染迭代中进行,因为变换矩阵会经常变动):

    int modelLoc = glGetUniformLocation(ourShader.ID, "model");
    glUnifromMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
    ...
    //观察矩阵和投影矩阵类似
    

    绘制旋转的立方体

    随时间旋转函数:

    model = glm::rotate(model, (float)glfwGetTime() * glm::radians(50.0f), glm::vec3(0.5, 1.0f, 0.0f));
    

    使用glDrawArrays绘制立方体,总共36个顶点。

    glDrawArrays(GL_TRIANGLES, 0, 36);
    

    开始深度测试

    z缓冲也叫深度缓冲(Depth Buffer),所有的深度信息都存储在其中。OpenGL会根据深度值来判断物体是否被遮挡,若是则丢弃。这个过程称为深度测试(Depth Testing),开启它需要添加以下函数:

    glEnable(GL_DEPTH_TEST);
    

    在每次迭代前需要清除深度缓冲:

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    

    绘制更多立方体

    首先在一个glm::vec3数组中定义10个立方体位置:

    glm::vec3 cubePositions[] = {
      glm::vec3( 0.0f,  0.0f,  0.0f), 
      glm::vec3( 2.0f,  5.0f, -15.0f), 
      glm::vec3(-1.5f, -2.2f, -2.5f),  
      glm::vec3(-3.8f, -2.0f, -12.3f),  
      glm::vec3( 2.4f, -0.4f, -3.5f),  
      glm::vec3(-1.7f,  3.0f, -7.5f),  
      glm::vec3( 1.3f, -2.0f, -2.5f),  
      glm::vec3( 1.5f,  2.0f, -2.5f), 
      glm::vec3( 1.5f,  0.2f, -1.5f), 
      glm::vec3(-1.3f,  1.0f, -1.5f)  
    };
    

    在渲染循环当中调用glDrawArrays10次:

    for (unsigned int i = 0; i < 10; i++) {
        // calculate the matrix for each object and pass it to shader before drawing
        glm::mat4 model;
        model = glm::translate(model, cubePositions[i]);
        float angle = 20.0f * (i + 1);
        model = glm::rotate(model, (float)glfwGetTime() * glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
        ourShader.setMat4("model", model);
        
        glDrawArrays(GL_TRIANGLES, 0, 36);
    }
    

    最终绘制效果如下:


    动图加载比较慢,请耐心等待动图加载比较慢,请耐心等待

    相关文章

      网友评论

        本文标题:坐标系统

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