Can i use OpenGL features from qt without having any kind of widget?


Keywords:c++ 


Question: 

I'm trying to compute something on gpu using openGL compute shaders. But i want to keep this program in terminal, so i don't want any kind of widgets.

For now it looks like i won't be able to call initializeOpenGLFunctions() or any others ogl related functions without getting Segmentation fault.

Header

#include <QOpenGLShaderProgram>
#include <QOpenGLFunctions_4_5_Core>

class SolverGPU : public QObject,
                  protected QOpenGLFunctions_4_5_Core
{
    Q_OBJECT
public:
    SolverGPU();

private:
    QOpenGLShaderProgram* program;
};

Src

SolverGPU::SolverGPU()
{
    initializeOpenGLFunctions();
    program = new QOpenGLShaderProgram();
    program->addShaderFromSourceFile(QOpenGLShader::Compute, ":/shaders/compute.glsl");
    program->link();
    program->bind();
}

I've already tried using QOpenGLFunctions instead of QOpenGLFunctions_4_5_Core, that didn't worked.


1 Answer: 

The following code works for me. The box I'm working at right now doesn't support OpenGL 4.5, hence the `downgrade' to 3.3. The principle's the same though.

#include <cstdlib>
#include <iostream>
#include <QApplication>
#include <QOffscreenSurface>
#include <QOpenGLContext>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>

int main (int argc, char **argv)
{
  try {
    QApplication app(argc, argv);

    QSurfaceFormat format;
    format.setMajorVersion(3);
    format.setMinorVersion(3);
    format.setProfile(QSurfaceFormat::CoreProfile);

    QOpenGLContext gl_ctx;
    gl_ctx.setFormat(format);
    if (!gl_ctx.create())
      throw std::runtime_error("context creation failed");

    QOffscreenSurface surface;
    surface.create();
    gl_ctx.makeCurrent(&surface);

    QOpenGLFunctions_3_3_Core opengl_functions;
    if (!opengl_functions.initializeOpenGLFunctions())
      throw std::runtime_error("initialization failed");

    QOpenGLShader vertex_shader(QOpenGLShader::Vertex);
    if (!vertex_shader.compileSourceCode(
          "#version 330 core\n"
          "\n"
          "void main ()\n"
          "{\n"
          "  gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
          "}\n"
          )) {
      throw std::runtime_error("vertex shader compilaton failed");
    }

    QOpenGLShader fragment_shader(QOpenGLShader::Fragment);
    if (!fragment_shader.compileSourceCode(
          "#version 330 core\n"
          "\n"
          "layout(location = 0) out vec4 colour;\n"
          "\n"
          "void main ()\n"
          "{\n"
          "  colour = vec4(0.0, 0.0, 0.0, 1.0);\n"
          "}\n"
          )) {
      throw std::runtime_error("fragment shader compilaton failed");
    }

    QOpenGLShaderProgram program;
    if (!program.addShader(&vertex_shader))
      throw std::runtime_error("failed to add vertex shader to program");
    if (!program.addShader(&fragment_shader))
      throw std::runtime_error("failed to add fragment shader to program");
    if (!program.link())
      throw std::runtime_error("failed to link failed");
    if (!program.bind())
      throw std::runtime_error("glUseProgram failed");

    app.exec();
  }
  catch (std::exception &ex) {
    std::clog << "\n" << ex.what();
  }
  catch (...) {
    std::clog << "\nunrecognized exception";
  }
  exit(0);
}

I've only performed minimal testing but the code shown creates a suitable context, initializes the 3.30 core function set and successfully compiles and links a shader program.