当前位置: 首页 > 知识库问答 >
问题:

透视投影的一些混淆

刘弘济
2023-03-14

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

考虑一个简单的正方形。<br>在使用透视投影之前,我可以定义其顶点在[-1,1]空间中的坐标,对于{0.0f,0.0f,0.0 f,1.0f、1.0f、1.0 f、1,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;
}

共有2个答案

昌博易
2023-03-14

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

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

卫嘉谊
2023-03-14

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

你可以看到glm的最后两个参数::p频谱调用,它们定义了近和远的剪辑距离。您的正方形位于 Z=0,因此没有进一步的变换,因此会从观看音量中掉落。解决方案:在 -Z 方向上移动几个单位。

请注意以下对近值和远值的约束:

>

  • abs(far)

    sgn(近)=sgn(远)

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

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

      < li>abs(near)应该尽可能大 < li>abs(far)应尽可能小。

  •  类似资料:
    • 举个简单的例子来说明正交投影与透视投影照相机的区别。使用透视投影照相机获得的结果是类似人眼在真实世界中看到的有“近大远小”的效果(如下图中的(a));而使用正交投影照相机获得的结果就像我们在数学几何学课上老师教我们画的效果,对于在三维空间内平行的线,投影到二维空间中也一定是平行的(如下图中的(b))。 (a)透视投影,(b)正交投影 那么,你的程序需要正交投影还是透视投影的照相机呢? 一般说来,对

    • 在这一节中我们将会介绍如何在保持深度外观的情况下将三维世界中的物体投影到二维平面上去。最有代表性的例子是:当我们站在一条笔直的马路的中间向前看时,我们会发现马路的两边会越来越靠近,并最终汇聚成一个点。这就是图形学中常说的透视投影。 为了实现上面的效果,在本节中我们需要生成一个投影矩阵,这个投影矩阵需要满足能够将所有的顶点都投影到范围位于 -1 到 1 之间的规范化空间中(normalizedspa

    • 透视投影照相机(Perspective Camera)的构造函数是: THREE.PerspectiveCamera(fov, aspect, near, far) 让我们通过一张透视照相机投影的图来了解这些参数。 透视图中,灰色的部分是视景体,是可能被渲染的物体所在的区域。fov是视景体竖直方向上的张角(是角度制而非弧度制),如侧视图所示。 aspect等于width / height,是照相

    • 针对不同应用的三维场景需要使用不同的投影方式,比如机械、工业设计领域常常采用正投影(平行投影), 大型游戏场景往往采用透视投影(中心投影)。为了完成三维场景不同的投影方式,three.js封装WebGL API和相关算法,提供了正投影相机OrthographicCamera和透视投影相机PerspectiveCamera。 正投影和透视投影简单解释 下面对正投影相机和透视投影相机的投影算法进行简单

    • 本文向大家介绍OpenGL ES透视投影实现方法(四),包括了OpenGL ES透视投影实现方法(四)的使用技巧和注意事项,需要的朋友参考一下 在之前的学习中,我们知道了一个顶点要想显示到屏幕上,它的x、y、z分量都要在[-1,1]之间,我们回顾一下渲染管线的图元装配阶段,它实际上做了以下几件事:剪裁坐标、透视分割、视口变换。图元装配的输入是顶点着色器的输出,抓哟是物体坐标gl_Position,