[英]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函數的文件(而非小部件)之間共享相同的上下文,則可以:
指定上下文和表面設置(您可以在父窗口小部件中甚至在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發生沖突。
這是相當簡單的,並且到目前為止已經可以使用。 只需包含所需的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.