【问题标题】:How to share OpenGL 3.3+ functions and context between files in a Qt 5.4 program如何在 Qt 5.4 程序中的文件之间共享 OpenGL 3.3+ 函数和上下文
【发布时间】:2015-04-30 18:21:32
【问题描述】:

目前正在尝试将 SDL2 / GLEW OpenGL 3.3 程序移植到 Qt 以使用 GUI 工具,但是由于我实际上需要使用窗口空间,所以我不能只从 QOpenGLWindow 继承。我必须初始化一个新的小部件,然后使用 QVBoxLayout 小部件将其添加到窗口中:

//in oglWidget.hpp file
class OGLWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_2_Core
{
  Q_OBJECT

private:
  bool m_core;
  bool mTest;

public slots:
  void cleanup();

public:
  OGLWidget(QWidget *parent = 0);
  ~OGLWidget();

  QSize minimumSizeHint() const Q_DECL_OVERRIDE;
  QSize sizeHint() const Q_DECL_OVERRIDE;

  void initializeGL() Q_DECL_OVERRIDE;
  void paintGL() Q_DECL_OVERRIDE;
  void resizeGL(int width, int height) Q_DECL_OVERRIDE;
  void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
  void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
};

//inside mainWindow.cpp
...
  QSurfaceFormat format;
  format.setDepthBufferSize(24);
  format.setStencilBufferSize(8);
  format.setVersion(3, 2);
  format.setProfile(QSurfaceFormat::CoreProfile);

  glRenderer = new OGLWidget();
  glRenderer->setFormat(format);
  ui->openglLayout->addWidget(glRenderer);
...
//in oglWidget.cpp
void OGLWidget::initializeGL() 
{
  //from parent class
  this->initializeOpenGLFunctions();

  //deals with unexpected closeings due to foreign widgets etc
  connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &OGLWidget::cleanup);

  QString versionString(QLatin1String(reinterpret_cast<const char*>(glGetString(GL_VERSION))));
  qDebug() << "Driver Version String:" << versionString;
  qDebug() << "Current Context:" << this->format();
}

这让我可以按原样使用 OpenGL API,只需在需要时调用它。问题是我似乎无法在文件之间共享它,例如纯静态的资源管理器类,甚至不是静态的着色器管理器类。我只能从这个 odlWidget.cpp 文件访问 OpenGL。我似乎不知道如何授予对其他文件的访问权限,因为 GLEW 只需要包含在需要访问权限的任何地方。

以下会产生 segFault:

//in shadermanager.hpp
class ShaderManager
{
private:
  void checkForErrors(GLuint object, std::string type);
  QOpenGLFunctions_3_2_Core *glFuncs;
public:
  GLuint ID;
  ShaderManager() {glFuncs->initializeOpenGLFunctions();}
}

Qt 需要什么才能共享 OpenGL API?上下文?我是否必须将当前的 QOpenGLFunctions_3_2_Core 对象传递给每次都必须访问 OpenGL 的对象?这方面的文档(包括示例)只是对所有 OpenGL 相关函数使用单个文件,而唯一不使用的文档(框示例)将注释包含添加到 GLEW。

解决这个问题的最佳方法是什么?

我正在运行 Xubuntu LTS 64 位,我可以确认驱动程序和库已正确安装,因为 SDL2 / GLEW 版本可以正常编译和运行。

【问题讨论】:

  • 确保你的ShaderManager是在你有一个OpenGL上下文之后创建的(不知道QT,所以我猜是initializeGL之后)。此外,如果您在 initializeGL 中重新加载 GL 函数,则在 ShaderMAnager 中重新加载是多余的。
  • 它是,仍然不会编译。编辑:我的错,它编译它只是段错误。
  • 不会编译?你说它有段错误。编译器错误和源代码是什么?此外,您不会在构造函数中初始化 ShaderManager.glFuncs

标签: c++ linux qt opengl opengl-es


【解决方案1】:

好吧,经过多次头疼后,我想出了 2 个可行的解决方案,将它们发布出来以防有人需要帮助,因为缺乏有关这种特定情况的资源。

注意:这是在 QT 5.4 for linux / xubuntu LTS 上测试的。

如果您需要在需要 opengl 函数的文件(而不是小部件)之间共享相同的上下文,您可以:

1。使用 GLEW 管理可用的 opengl 函数。

指定上下文和表面设置(您可以在父窗口小部件中甚至在 main.cpp 文件本身中执行此操作)。

int main(int argc, char *argv[])
{
  QSurfaceFormat format;
  format.setDepthBufferSize(24);
  format.setStencilBufferSize(8);
  format.setVersion(3, 2);
  format.setProfile(QSurfaceFormat::CoreProfile);
  //here qt will set this as the default format for the rest of the app
  //and will use it to implicitly initialize any object that requires one
  QSurfaceFormat::setDefaultFormat(format);

  QApplication a(argc, argv);
  MainWindow w;
  w.show();

  return a.exec();
}

获得有效上下文后,初始化 GLEW。

#define GLEW_STATIC
#include <GL/glew.h>
//inside a class that inherits from QOpenGLWidget
//if you rather not inherit, you have to instance a QtOpenGLContext yourself
  this->makeCurrent();
  glewExperimental = GL_TRUE;
  GLenum glew_status = glewInit();
  if(glew_status != GLEW_OK)
    {
      fprintf(stderr, "Error %s\n", glewGetErrorString(glew_status));
    }

然后,每当您需要访问 opengl API 时,只需在头文件中添加以下代码即可。

#include <GL/glew.h>
#define QT_NO_OPENGL_ES_2

但是,由于最近对 Qt 的更改,只有在您使用 -opengl 桌面配置编译 QT 时才能使用 GLEW。如果你不这样做,它仍然会处理严重的错误(这是创建线程的原因),如果你检查错误,opengl error 1280 会弹出,这是因为默认情况下,Qt 的 opengl 实现是 openglES 的,并且它会与 GLEW 发生冲突。

2。使用 Qt 的 opengl 包装器

这是相当简单的,并且似乎到目前为止工作。只需包含所需的 qtopengl 函数(请注意,从 5.2 开始,有很多不同的头文件,每个头文件都有自己的版本)或简单地使用 QOpenglFunctions。

然后,每次您需要访问 API 时,只需包含函数对象的实例并通过该对象访问 opengl。

#include <QOpenGLFunctions>

...

    QOpenGLFunctions *glFuncs = QOpenGLContext::currentContext()->functions();
    glFuncs->glCompileShader(example);

请注意,您仍然需要一个有效的上下文,它可以按照与 GLEW 示例中相同的方式创建。

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 2011-07-26
    • 2013-09-23
    • 1970-01-01
    • 1970-01-01
    • 2018-10-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-16
    • 2013-07-10
    相关资源
    最近更新 更多