如何在Qt 5.4程序

时间:2015-04-30 18:21:32

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

目前正在尝试将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版本编译并正常运行。

1 个答案:

答案 0 :(得分:1)

好吧,在经历了许多令人头疼的事情之后,我提出了两个可行的解决方案,如果有人需要帮助,可以发布这些解决方案,因为缺乏关于这种特定情况的资源。

注意:这是在QT 5.4上针对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示例中的相同。

希望它有所帮助。