目前正在尝试将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版本编译并正常运行。
答案 0 :(得分:1)
好吧,在经历了许多令人头疼的事情之后,我提出了两个可行的解决方案,如果有人需要帮助,可以发布这些解决方案,因为缺乏关于这种特定情况的资源。
注意:这是在QT 5.4上针对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示例中的相同。
希望它有所帮助。