glFrustum没有创建透视图

时间:2018-09-23 00:53:57

标签: c++ opengl perspectivecamera projection-matrix

我正在尝试使用C ++和openGL创建3D操作程序。我对openGL比较陌生,因此我经常不得不查找文档以找到合适的功能来完成我想要的事情。我以为我对正交投影和透视投影有了很好的了解(glOrtho创建了一个正交投影,其中不同的z值看起来并不相同,glFrustum创建了一个透视投影,其中z值是仔细看越大)。但是,当我在程序中换出glOrthoglFrustum时,看不出任何区别。我在下面复制了一个显示效果的小程序。作为参考,我将openGL与freeglut一起使用。

#include "GL/freeglut.h"
void initFunc()
{
    glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-1, 1, -1, 1, -1, 1);

}

void displayFunc()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);

    glColor3f(1.0f, 1.0f, 0.0f);
    glLineWidth(1.0f);
    glutWireTeapot(0.3);

    glTranslatef(0, -0.5, -0.5);
    glutWireTeapot(0.3);

    glutSwapBuffers();
}

int main(int argc, char ** argv)
{
    glutInit(&argc, argv);
    glutInitWindowSize(600, 600);
    glutInitWindowPosition(0, 0);

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    glutCreateWindow("Teapot Perspective");

    initFunc();

    glutDisplayFunc(displayFunc);

    glutMainLoop();
}

我正在绘制两个茶壶,它们在y和z轴上都略有偏移。据我了解,glOrtho应该使两个茶壶具有相同的位置,并且仅具有y偏移,而glFrustum应该使其中一个比另一个大。但是,它们都使茶壶完全相同。

我在这里错过了什么吗?我还需要采取其他步骤来正确设置透视投影吗?还是我误解了glFrustum的工作方式?我也尝试过使用gluPerspective而不是glFrustum,但是我似乎找不到合适的值来使用。我尝试使用FOV为90,纵横比为1以及各种z值的方法,但它们要么不生产茶壶,要么变形的茶壶无法识别。此外,gluPerspective的行为似乎与带有相应参数的glFrustum调用不同。我不确定我在这里缺少什么。

1 个答案:

答案 0 :(得分:1)

在正交投影上,由于w分量为1(对于笛卡尔输入坐标),视图空间中的坐标线性映射到剪辑空间坐标,并且剪辑空间坐标等于规范化的设备坐标。
左,右,下,上,近和远的值定义一个框。盒子体积内的所有几何图形在视口上都是“可见的”。

glOrtho定义的正交投影矩阵为:

r = right, l = left, b = bottom, t = top, n = near, f = far

x:  2/(r-l)         0               0               0
y:  0               2/(t-b)         0               0
z:  0               0               -2/(f-n)        0
t:  -(r+l)/(r-l)    -(t+b)/(t-b)    -(f+n)/(f-n)    1

在“透视投影”中,投影矩阵描述了从针孔相机中看到的世界3D点到视口的2D点的映射。
摄像机视锥台(截头金字塔)中的眼睛空间坐标映射到立方体(规范化的设备坐标)。

透视投影矩阵可以由平截头体(glFrustum)定义。
距离leftrightbottomtop是指从视点中心到视锥面在近平面上的距离。 nearfar指定了平截头体上到近平面和远平面的距离。

r = right, l = left, b = bottom, t = top, n = near, f = far

x:  2*n/(r-l)      0              0                0
y:  0              2*n/(t-b)      0                0
z:  (r+l)/(r-l)    (t+b)/(t-b)    -(f+n)/(f-n)    -1
t:  0              0              -2*f*n/(f-n)     0

您提出这样的规范:

glFrustum(-1, 1, -1, 1, -1, 1);

没有定义适当的视锥,因为近平面的值为负,远平面的值为正。

如果要检查OpenGL错误(通过glGetError),则将得到INVALID_OPERATION错误。

OpenGL 4.6 API Compatibility Profile Specification; 12.1. FIXED-FUNCTION VERTEX TRANSFORMATIONS; page 501: >

void Frustum( double l, double r, double b, double t, double n, double f );
     

坐标(l b −n)T和(r t −n)T指定近裁剪平面上的点分别映射到窗口的左下角和右上角(假设眼睛位于(0 0 0)T)。 f给出了从眼睛到远裁剪平面的距离。

     

错误   如果 n <= 0 f <= 0l == rb == tn == f,则生成INVALID_VALUE错误。

相关问题