Qt、openGL、小部件和离屏渲染

Qt, openGL, widgets and offscreen rendering

我正在 RedHat Linux 上开发,cat /etc/redhat-release:

    Red Hat Enterprise Linux Workstation release 7.2 (Maipo)

我正在使用 Qt Creator 4.3.1:

    Based on Qt 5.9.1 (GCC 5.3.1 20160406 (Red Hat 5.3.1-6), 64 bit)

我正在开发的项目使用 Qt 5.6.2 GCC 64 位,该项目是使用派生自 QWidget 的图形对象开发的,其中包括实时视频流。

不幸的是,我们在播放视频时遇到了撕裂现象,这在视频周围显示的其他小部件中也很明显,我认为这是因为视频没有使用垂直同步。

我相信使用openGL会纠正这种情况,目的是使用openGL重写包括视频播放在内的小部件。我花了几天时间试图找到完整且有效的解决方案,但到目前为止未能找到完整且有效的解决方案。

我一直在考虑在我用来测试的小部件中使用 QOpenGLWidget:

    class clsElevStrip : public QOpenGLWidget, protected QOpenGLFunctions {
    Q_OBJECT

在构造函数中,我设置了离屏渲染的格式:

    //Create surface format for rendering offscreen
    mobjFormat.setDepthBufferSize(24);
    mobjFormat.setSamples(4);
    mobjFormat.setVersion(3, 0);
    mobjFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
    setFormat(mobjFormat);

在 paintGL 方法中:

    QOpenGLContext* pobjContext = context();
    QSurface* pobjSurface = pobjContext->surface();
    assert(pobjSurface != NULL);

    int intSB1 = pobjSurface->format().swapBehavior();
    qDebug() << (QString("paintGL:format: ")
               + QString::number(intSB1));
    pobjContext->makeCurrent(pobjSurface);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glBegin(GL_TRIANGLES);
    glColor3f(1.0, 0.0, 0.0);
    glVertex3f(-0.5, -0.5, 0);
    glColor3f(0.0, 1.0, 0.0);
    glVertex3f( 0.5, -0.5, 0);
    glColor3f(0.0, 0.0, 1.0);
    glVertex3f( 0.0,  0.5, 0);
    glEnd();

    pobjContext->swapBuffers(pobjSurface);

主显示屏上什么都看不到,调试语句显示格式为 2 (DoubleBuffering)。

如果我注释掉构造函数中的行:

    setFormat(mobjFormat);

调试语句显示格式为 0 (DefaultSwapBehavior)。而且图形是可见的,我错过了什么?

您的问题的解决方案很简单:

只是不要所有 QOpenGLGLContext jugging。 paintGL 的全部要点是,这个特定函数是在包装器内调用的,该包装器已经为您完成了所有上下文杂耍。 **无需调用 makeCurrentswapBuffers。 Qt 已经为您做到了!

来自 Qt 文档

void QOpenGLWidget::paintGL()

This virtual function is called whenever the widget needs to be painted. Reimplement it in a subclass.

There is no need to call makeCurrent() because this has already been done when this function is called.

Before invoking this function, the context and the framebuffer are bound, and the viewport is set up by a call to glViewport(). No other state is set and no clearing or drawing is performed by the framework.

如果你只有这个作为你的 paintGL 它会显示一些东西,如果你有 兼容性配置文件 >=OpenGL-3.x 上下文或者如果您使用的是 <=OpenGL-2.x 上下文。 您在那里使用的是遗留的固定功能管道,它将 不会 使用 OpenGL-3.x 核心配置文件上下文!

void glwidget::paintGL(){
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glBegin(GL_TRIANGLES);
    glColor3f(1.0, 0.0, 0.0);
    glVertex3f(-0.5, -0.5, 0);
    glColor3f(0.0, 1.0, 0.0);
    glVertex3f( 0.5, -0.5, 0);
    glColor3f(0.0, 0.0, 1.0);
    glVertex3f( 0.0,  0.5, 0);
    glEnd();
}