【问题标题】:Some confusion about Perspective projection关于透视投影的一些困惑
【发布时间】:2012-07-30 06:58:22
【问题描述】:

我刚刚了解了透视投影,并且发现在 openGl 中应用它有点令人困惑。

考虑一个简单的正方形。
在使用透视投影之前,我可以在 [-1,1] 空间中定义其顶点的坐标,输入为 {0.0f,0.0f,0.0f,1.0f,1.0f,1.0f,1.0f,0.0 f} ,正方形将占据窗口的第一象限。
考虑我的代码中的以下部分:

设置矩阵:

    glm::mat4 mvp(1.0);
    mvp*=glm::perspective(45.0f,1.0f,0.01f,100.0f);

制服:

    loc = glGetUniformLocation(program.getHandle(),"mvp");
    glUniformMatrix4fv(loc,1,GL_FALSE,glm::value_ptr(mvp));

顶点着色器:

    #version 330
    in vec2 pos;
    uniform mat4 mvp;
    void main()
    {
        gl_Position = mvp*vec4(pos,0.0f,1.0f);
    }

但是,结果是一个空白屏幕。
我需要在这里应用哪些额外的转换?
另外,顶点数据应该在哪个坐标中?

完整代码如下:

#include "program.h"
#include <GL/glew.h>
#include <SFML/Window.hpp>
#include <stdexcept>
#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/core/type.hpp>

void GlewInit()
{
        GLenum err = glewInit();
        if (GLEW_OK != err)
        {
                std::cerr<<"Error: "<<glewGetErrorString(err)<<std::endl;
                throw(std::runtime_error("GLEW_INIT Failure."));
        }
}
int main()
{
    sf::Window win(sf::VideoMode(400,400),"Manasij");
    GlewInit();
    float vertexdata[]={0.0f,0.0f,0.0f,1.0f,1.0f,1.0f,1.0f,0.0f};
    GLubyte indexdata[]={0,1,2,3};
    float colordata[]={0.3f,0.0f,0.5f,1.0f};
    mm::Program program
    (
        {
            mm::Shader(GL_VERTEX_SHADER,"vshader.vert"),
            mm::Shader(GL_FRAGMENT_SHADER,"fshader.frag")
        }
    );

    glm::mat4 mvp(1.0);

    mvp*=glm::perspective(45.0f,1.0f,0.01f,100.0f);


    GLuint vao,vbo,ibo;
    glGenVertexArrays(1,&vao);
    glBindVertexArray(vao);

    glGenBuffers(1,&vbo);
    glBindBuffer(GL_ARRAY_BUFFER,vbo);
    glBufferData(GL_ARRAY_BUFFER,8*sizeof(GLfloat),vertexdata,GL_STATIC_DRAW);

    glGenBuffers(1,&ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,4*sizeof(GLubyte),indexdata,GL_STATIC_DRAW);

    glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,0,0);
    glEnableVertexAttribArray(0);
    glBindAttribLocation(program.getHandle(),0,"pos");


    glUseProgram(program.getHandle());
    auto loc = glGetUniformLocation(program.getHandle(),"col");
    glUniform4fv(loc,1,colordata);
    loc = glGetUniformLocation(program.getHandle(),"mvp");
    glUniformMatrix4fv(loc,1,GL_FALSE,glm::value_ptr(mvp));
    glUseProgram(0);


    glClearColor(1.0f,1.0f,1.0f,1.0f);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    while(win.isOpen())
    {
        glClear(GL_COLOR_BUFFER_BIT);
        glUseProgram(program.getHandle());
//      glDrawArrays(GL_QUADS,0,4);
        glDrawElements(GL_QUADS,4,GL_UNSIGNED_BYTE,nullptr);
        glUseProgram(0);

        win.display();
        sf::Event eve;
        while(win.pollEvent(eve))
            if(eve.type==sf::Event::Closed)
                win.close();
    }
    return 0;
}

【问题讨论】:

  • 你可以改变 glm::mat4 mvp(1.0); mvp*=glm::perspective(45.0f,1.0f,0.01f,100.0f);进入 glm::mat4 mvp = glm::perspective(...);我想。

标签: opengl graphics perspective


【解决方案1】:

但是,结果是一个空白屏幕。 我需要在这里应用哪些额外的转换?

您会看到glm::perspective 调用的最后两个参数,它们定义了近剪辑距离和远剪辑距离。您的正方形位于 Z=0 处,无需进一步转换,因此会超出查看体积。解决方案:将seqare向-Z方向移动几个单位。

注意以下对近值和远值的限制:

  • abs(远) > abs(near) > 0

  • sgn(near) = sgn(far)

如果 sgn(near) = sgn(far) = -,您还必须交换深度范围的符号,或者将深度测试函数更改为 GL_LESS。

由于深度缓冲区分辨率不是线性分布,而是以类似 1/z 的方式分布

  • abs(near) 应尽可能大
  • abs(far) 应尽可能小。

【讨论】:

  • 我刚改了“gl_Position = mvpvec4(pos,0.0f,1.0f);”到“gl_Position = mvpvec4(pos,0.5f,1.0f);”并且 glDepthFunc 已经设置为 GL_LESS ;但我得到了同样的结果。我在上面发布了源代码。
【解决方案2】:

也许这个网站可以帮助你,它解释了 OpenGL 中投影矩阵的设置:

http://www.songho.ca/opengl/gl_projectionmatrix.html

【讨论】:

    猜你喜欢
    • 2019-11-07
    • 1970-01-01
    • 1970-01-01
    • 2014-11-02
    • 2016-09-15
    • 2017-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多