在 Qt 的外部类中使用 OpenGL 上下文

Posted

技术标签:

【中文标题】在 Qt 的外部类中使用 OpenGL 上下文【英文标题】:Use OpenGL context in an external class in Qt 【发布时间】:2014-12-08 14:42:03 【问题描述】:

我在 Qt 中有一个继承自 QGLViewer 的窗口。如果我在该类中创建任何着色器程序,QGLShaderProgram myShader 一切运行正常。

但是,我开始将一些渲染调用移动到具有 draw()call 的类之外的类,并且事情被破坏了。

应用程序编译正常,没有错误,但执行时收到错误The program has unexpectedly finished

我发现从 Qt4 到 Qt5,着色器类发生了变化,在 Qt5 中使用的是 QOpenGLShaderProgram。我试了一下,同样的问题出现了,但是我收到了不同的错误消息QOpenGLFunctions created with a non-current context

这让我觉得当从一个与实际执行绘图的类没有直接关系的类调用 OpenGL 函数时,OpenGL 上下文“丢失”了。

如何使上下文在所有类中可见?一般来说,我的代码看起来像

MyViewer.hpp

class MyViewer : public QGLViewer

   MyViewer(const QGLFormat format);
   ~MyViewer();

protected:
   init();
   draw()
   
      // Clear color buffer and depth buffer
      // Do stuff
      m_cube.render();
   
private:
   ...
   ...

   Cube m_cube;
;

Cube.cpp

class Cube

public:
   Cube()
   
      m_shaderProgram.addShaderFromSourceFile(QGLShader::Vertex, ":/vertex.glsl");
      m_shaderProgram.addShaderFromSourceFile(QGLShader::Fragment, ":/fragment.glsl");
      m_shaderProgram.link();

      //Initialize VAO and VBOs
   

   void render() // render OpenGL calls 

private:
   QGLShaderProgram m_shaderProgram;
;

【问题讨论】:

OpenGL 上下文绑定到特定线程,但在其他方面是全局的。您很可能在创建上下文之前尝试调用 OpenGL 函数(例如,通过创建着色器)。 【参考方案1】:

Open gl 上下文是全局的,但您可以像这样在 2 个查看器之间显式共享上下文

QGLViewer   (   QGLContext *    context,
        QWidget *   parent = 0,
        const QGLWidget *   shareWidget = 0,
        Qt::WindowFlags     flags = 0 
    )   

根据文献

与 QGLViewer() 相同,但可以提供一个 QGLContext 以便查看者 共享 GL 上下文,即使使用 QGLContext 子类(使用 shareWidget 否则)。

所以首先检查你创建类的顺序。因为 Cube 可能正在调用 opengl 函数,而您的查看器仍然不完整 如果在 QGLviewer 创建上下文之前调用 opengl 函数,则会出现错误。

如果是这样,一个快速的解决方法是在您的立方体构造器中创建一个新的 Qglcontext 并将其传递回查看器。

别这样

Cube() ; // empty cube constructor
void InitShaders()
   
      m_shaderProgram.addShaderFromSourceFile(QGLShader::Vertex, ":/vertex.glsl");
      m_shaderProgram.addShaderFromSourceFile(QGLShader::Fragment, ":/fragment.glsl");
      m_shaderProgram.link();

      //Initialize VAO and VBOs
   

在我的查看器的构造函数中做

MyViewer(const QGLFormat format)
    cube.initShaders();


我没有测试过这段代码,但它应该会改变初始化的顺序。

【讨论】:

以上是关于在 Qt 的外部类中使用 OpenGL 上下文的主要内容,如果未能解决你的问题,请参考以下文章

带有 OpenGL 上下文的基于 Qt 的命令行工具

是否可以在 Qt 的***窗口之间使用相同的 OpenGL 上下文?

如何使用 Qt 4 创建 OpenGL 3 上下文?

在 OS X 上的 Qt 4.8.6 中更改 QGLWidgets 的 OpenGL 上下文版本

树莓派上的 Qt OpenGL 上下文

在 Qt 中创建原始 GL 上下文?