簡體   English   中英

如何在Qt 5.4程序中的文件之間共享OpenGL 3.3+功能和上下文

[英]How to share OpenGL 3.3+ functions and context between files in a Qt 5.4 program

當前正在嘗試將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添加注釋的包含。

解決此問題的最佳方法是什么?

我正在運行64位的Xubuntu LTS,我可以確認驅動程序和庫已正確安裝,因為SDL2 / GLEW版本可以編譯並正常運行。

好吧,在經歷了許多頭痛之后,我想出了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錯誤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示例中的上下文相同的方式來創建它。

希望能幫助到你。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM