Qt 和 openGL 的 gluPerspective 等效项

Posted

技术标签:

【中文标题】Qt 和 openGL 的 gluPerspective 等效项【英文标题】:gluPerspective equivalent for Qt and openGL 【发布时间】:2013-05-05 17:51:17 【问题描述】:

我正在尝试让 Qt 和 openGL 一起工作,这样我就可以消除 glu 和 glut。

除了我的透视矩阵,我的一切都按我的意愿工作。

我只是在画一个简单的 3D 立方体,并希望我的视点有一个角度。

我已尝试编写 gluPerspective 的替代代码,但无法得到我想要的。

因此,我怎样才能让透视矩阵正常工作?

注意:我对其他替代方案持开放态度,因为我仍在尝试习惯 openGL 和 Qt,以及如何正确使用这两个框架。

下面是我的 GLWidget 类的实现:

GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent) 
    setMouseTracking(true);


void GLWidget::initializeGL() 
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glEnable(GL_DEPTH_TEST);


void GLWidget::resizeGL(int w, int h) 
    glViewport(0,0,w,h);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-30.0, 30.0, -30.0, 30.0, -30.0, 30.0);

    GLdouble aspect = w / (h ? h : 1);

    const GLdouble zNear = -30.0, zFar = 30.0, fov = 30.0;

    perspective(fov, aspect, zNear, zFar);

    glMatrixMode(GL_MODELVIEW);


void GLWidget::paintGL() 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3f(1.0, 1.0, 1.0);

    glBegin(GL_LINE_LOOP);
    glVertex3iv(a);
    glVertex3iv(b);
    glVertex3iv(c);
    glVertex3iv(d);
    glEnd();

    glBegin(GL_LINE_LOOP);
    glVertex3iv(a);
    glVertex3iv(e);
    glVertex3iv(f);
    glVertex3iv(b);
    glEnd();

    glBegin(GL_LINE_LOOP);
    glVertex3iv(d);
    glVertex3iv(h);
    glVertex3iv(g);
    glVertex3iv(c);
    glEnd();

    glBegin(GL_LINE_LOOP);
    glVertex3iv(e);
    glVertex3iv(f);
    glVertex3iv(g);
    glVertex3iv(h);
    glEnd();



void GLWidget::keyPressEvent(QKeyEvent* event) 
    switch(event->key()) 
    case Qt::Key_Escape:
        close();
        break;
    default:
        event->ignore();
        break;
    


void GLWidget::perspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)

    GLdouble xmin, xmax, ymin, ymax;

    ymax = zNear * tan( fovy * M_PI / 360.0 );
    ymin = -ymax;
    xmin = ymin * aspect;
    xmax = ymax * aspect;

    glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );

【问题讨论】:

为什么不能继续使用glu? @AndreasHaferburg:也许 OP 的目标是长期放弃固定功能管道。 【参考方案1】:

您的透视函数是正确的(从某种意义上说,它与 gluPerspective() 所做的相同)。但你应该意识到 在 resizeGL() 中,您同时使用了 Ortho 和 Frustum,因此最终得到了一个投影矩阵 Ortho*Persepctive,它基本上在应用透视失真后添加了一些缩放和平移。

【讨论】:

好点,我只用我的透视矩阵进行测试,但是当我只使用我的透视矩阵时,我只得到一个黑屏,因为正交矩阵让我可以看到我的立方体。从我的透视函数返回一个矩阵,然后使用 glLoadMatrixd(...) 解决这个问题吗? @Pete:正如 Andreas Haferburg 在他的回答中所写,您当前的 fNear 值无效,因此您没有得到有用的输出也就不足为奇了。您不需要手动加载矩阵,在调用透视函数之前 LoadIdentity 就足够了。【参考方案2】:

您可以使用 glFrustum 重新实现 gluPerspective,或者您正在做面向未来的事情并使用 GLM、Eigen 或 linmath.h 等矩阵数学库,使用它计算矩阵并使用 glLoadMatrix 或 glUniform 将其加载到 OpenGL 中.

【讨论】:

【参考方案3】:

glFrustum 的 fNear 和 fFar 参数都必须为正数。

【讨论】:

以上是关于Qt 和 openGL 的 gluPerspective 等效项的主要内容,如果未能解决你的问题,请参考以下文章

gluPerspective 在 OpenGL 3.1 中被删除,有啥替代品吗?

OpenGL函数解析之gluPerspective()

OpenGL的gluPerspective函数详解[转]

openGL学习过程中资料总结

OpenGL中矩阵乘法的顺序

裁剪平面附近的 OpenGL