Issue with QGLFunctions (Updated, now OpenGL issue)



  • So I'm trying to make a QGLWidget function with Qt Creator and I'm running into a strange issue trying to use regular OpenGL functions. My program ASSERTS and crashes with: "QGLFunctions::isInitialized(d_ptr)" in "c:\work\build\qt5_workdir\w\s\qtbase\include\qtopengl../../src/opengl/qglfunctions.h, line 722"

    I found this is called from the "glGenBuffers" call in my cpp code. Ill post the .h and .cpp here:

    myglwidget.h
    @#ifndef MYGLWIDGET_H
    #define MYGLWIDGET_H

    #include <QGLWidget>
    #include <QGLFunctions>
    #include <QGLShaderProgram>

    class MyGLWidget : public QGLWidget, protected QGLFunctions
    {
    Q_OBJECT
    public:
    explicit MyGLWidget(QWidget *parent = 0);
    ~MyGLWidget();

    protected:
    void initializeGL();
    void paintGL();
    void resizeGL(int width, int height);

    private:
    int width;
    int height;
    GLuint back_texture;
    GLuint* vboid;
    QGLShaderProgram default_prog;
    };

    #endif // MYGLWIDGET_H
    @

    myglwidget.cpp
    @
    #include "myglwidget.h"
    #include <QDebug>
    #include <QVector3D>
    #include <QVector2D>
    #include "locale.h"

    #define BACK_TILE_S 48

    struct VertexData
    {
    QVector3D position;
    QVector2D texCoord;
    };

    MyGLWidget::MyGLWidget(QWidget *parent) :
    QGLWidget(parent)
    {
    glGenBuffers(2, vboid);
    }

    MyGLWidget::~MyGLWidget(){
    glDeleteBuffers(2, vboid);
    }

    void MyGLWidget::initializeGL(){
    VertexData verts[] = {
    {QVector3D(0, 0, 0), QVector2D(0, 0)},
    {QVector3D(1, 0, 0), QVector2D(1, 0)},
    {QVector3D(0, 1, 0), QVector2D(0, 1)},
    {QVector3D(1, 1, 0), QVector2D(1, 1)}
    };
    GLushort indices[] = {
    0, 1, 2, 3
    };

    setlocale(LC_NUMERIC, "C");
    
    default_prog.addShaderFromSourceFile&#40;QGLShader::Vertex, ":/shaders/default.vert"&#41;;
    default_prog.addShaderFromSourceFile(QGLShader::Fragment, ":/shaders/default.frag"&#41;;
    default_prog.link(&#41;;
    
    default_prog.bind(&#41;; // this is in initgl since this is the
                         // only shader we use... FOR NOW, therefore
                         // we dont have to do it elsewhere
    setlocale(LC_ALL, ""&#41;;
    
    glEnable(GL_TEXTURE_2D);
    // normally here we would have the QImage buffered up already
    // and would bind as needed, but again, this is the only
    // texture we use for now
    back_texture = bindTexture(QImage(":/gfx/gfx/back.png"));
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    
    glBindBuffer(GL_ARRAY_BUFFER, vboid[0]);
    glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(VertexData), verts, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboid[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4 * sizeof(GLushort), indices, GL_STATIC_DRAW);
    

    }

    void MyGLWidget::paintGL(){
    int texw;
    int texh;
    QMatrix4x4 proj;
    QMatrix2x2 scale;
    quintptr offset;
    int vertexLoc;
    int texcoordLoc;

    texw = (floor(width / ((double) BACK_TILE_S)) + 1);
    texh = (floor(height / ((double) BACK_TILE_S)) + 1);
    
    proj.setToIdentity();
    proj.scale(texw * BACK_TILE_S, texh * BACK_TILE_S);
    proj.ortho(0, width, 0, height, -1, 1);
    
    scale.setToIdentity();
    scale(0,0) = texw;
    scale(1,1) = texh;
    
    default_prog.setUniformValue("texScale", scale);
    default_prog.setUniformValue("mvp_matrix", proj);
    default_prog.setUniformValue("texture", 0);
    
    glBindBuffer(GL_ARRAY_BUFFER, vboid[0]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboid[1]);
    
    offset = 0;
    
    vertexLoc = default_prog.attributeLocation("a_position");
    default_prog.enableAttributeArray(vertexLoc);
    glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void*) offset);
    
    offset += sizeof(QVector3D);
    
    texcoordLoc = default_prog.attributeLocation("a_texcoord");
    default_prog.enableAttributeArray(texcoordLoc);
    glVertexAttribPointer(texcoordLoc, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void*) offset);
    
    glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
    

    }

    void MyGLWidget::resizeGL(int width, int height){
    this->width = width;
    this->height = height;
    }
    @


  • Lifetime Qt Champion

    Hi,

    I think you are missing the call to initializeGLFunctions in your initializeGL function



  • I tried it, got more issues, (now for something completely different!) and switched to try using GLEW... now even MORE problems. It just crashes at glewInit. No reason just ends unexpectedly.

    @#include <GL/glew64.h>
    #include "myglwidget.h"
    #include <QDebug>
    #include <QVector3D>
    #include <QVector2D>
    #include "locale.h"

    #define BACK_TILE_S 48

    struct VertexData
    {
    QVector3D position;
    QVector2D texCoord;
    };

    MyGLWidget::MyGLWidget(QWidget *parent) :
    QGLWidget(parent)
    {

    }

    MyGLWidget::~MyGLWidget(){
    //glDeleteBuffers(2, vboid);
    }

    void MyGLWidget::initializeGL(){
    VertexData verts[] = {
    {QVector3D(0, 0, 0), QVector2D(0, 0)},
    {QVector3D(1, 0, 0), QVector2D(1, 0)},
    {QVector3D(0, 1, 0), QVector2D(0, 1)},
    {QVector3D(1, 1, 0), QVector2D(1, 1)}
    };
    GLushort indices[] = {
    0, 1, 2, 3
    };

    makeCurrent();
    glewExperimental = GL_TRUE;
    
    int glewErr = glewInit();
    

    // if( glewErr != GLEW_OK )
    // {
    // qDebug("Error %s", glewGetErrorString(glewErr) ) ;
    // }
    /*

    setlocale(LC_NUMERIC, "C");
    
    default_prog.addShaderFromSourceFile&#40;QGLShader::Vertex, ":/shaders/default.vert"&#41;;
    default_prog.addShaderFromSourceFile&#40;QGLShader::Fragment, ":/shaders/default.frag"&#41;;
    default_prog.link();
    
    default_prog.bind(); // this is in initgl since this is the
                         // only shader we use... FOR NOW, therefore
                         // we dont have to do it elsewhere
    setlocale(LC_ALL, "");
    
    glEnable(GL_TEXTURE_2D);
    // normally here we would have the QImage buffered up already
    // and would bind as needed, but again, this is the only
    // texture we use for now
    back_texture = bindTexture(QImage(":/gfx/gfx/back.png"));
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    
    glGenBuffers(2, vboid);
    
    glBindBuffer(GL_ARRAY_BUFFER, vboid[0]);
    glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(VertexData), verts, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboid[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4 * sizeof(GLushort), indices, GL_STATIC_DRAW);
    */
    

    }

    void MyGLWidget::paintGL(){
    int texw;
    int texh;
    QMatrix4x4 proj;
    QMatrix2x2 scale;
    quintptr offset;
    int vertexLoc;
    int texcoordLoc;

    makeCurrent();
    
    
    texw = (floor(width / ((double) BACK_TILE_S)) + 1);
    texh = (floor(height / ((double) BACK_TILE_S)) + 1);
    /*
    proj.setToIdentity();
    proj.scale(texw * BACK_TILE_S, texh * BACK_TILE_S);
    proj.ortho(0, width, 0, height, -1, 1);
    
    scale.setToIdentity();
    scale(0,0) = texw;
    scale(1,1) = texh;
    
    default_prog.setUniformValue("texScale", scale);
    default_prog.setUniformValue("mvp_matrix", proj);
    default_prog.setUniformValue("texture", 0);
    
    glBindBuffer(GL_ARRAY_BUFFER, vboid[0]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboid[1]);
    
    offset = 0;
    
    vertexLoc = default_prog.attributeLocation("a_position");
    default_prog.enableAttributeArray(vertexLoc);
    glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void*) offset);
    
    offset += sizeof(QVector3D);
    
    texcoordLoc = default_prog.attributeLocation("a_texcoord");
    default_prog.enableAttributeArray(texcoordLoc);
    glVertexAttribPointer(texcoordLoc, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void*) offset);
    
    glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
    

    */
    }

    void MyGLWidget::resizeGL(int width, int height){
    this->width = width;
    this->height = height;
    }
    @


  • Lifetime Qt Champion

    IIRC, mixing with glew is a bad idea. Just thought about something, are you using Qt 5 ? If so you should move to the new QOpenGLXXX classes



  • Yes I am. Okay things are coming together because the man page on QGLFunctions warned against its use and I was thinking "Than what on earth am I supposed to use Qt?" So would I extend myglwidget with QOpenGLFunctions just like QGLFunctions?



  • I just tried extending to QOpenGLFunctions and I got the familiar "QOpenGLFunctions::isInitialized(d_ptr)" error.



  • Solved! had to makeCurrent() then call the similar initializeOpenGLFunctions.



  • Sooo close! But now I've run into the issue that my OpenGL code seems to flop, as in it won't draw anything but a black screen.

    Updated myglwidget.cpp
    @#include "myglwidget.h"
    #include <QDebug>
    #include <QVector3D>
    #include <QVector2D>
    #include "locale.h"

    #define BACK_TILE_S 48

    struct VertexData
    {
    QVector3D position;
    QVector2D texCoord;
    };

    MyGLWidget::MyGLWidget(QWidget *parent) :
    QGLWidget(parent)
    {

    }

    MyGLWidget::~MyGLWidget(){
    glDeleteBuffers(2, vboid);
    }

    void MyGLWidget::initializeGL(){
    VertexData verts[] = {
    {QVector3D(0, 0, 0), QVector2D(0, 0)},
    {QVector3D(1, 0, 0), QVector2D(1, 0)},
    {QVector3D(0, 1, 0), QVector2D(0, 1)},
    {QVector3D(1, 1, 0), QVector2D(1, 1)}
    };
    GLushort indices[] = {
    0, 1, 2, 3
    };
    makeCurrent();
    initializeOpenGLFunctions();

    setlocale(LC_NUMERIC, "C");
    
    default_prog.addShaderFromSourceFile&#40;QGLShader::Vertex, ":/shaders/default.vert"&#41;;
    default_prog.addShaderFromSourceFile&#40;QGLShader::Fragment, ":/shaders/default.frag"&#41;;
    default_prog.link();
    
    default_prog.bind(); // this is in initgl since this is the
                         // only shader we use... FOR NOW, therefore
                         // we dont have to do it elsewhere
    setlocale(LC_ALL, "");
    
    glDisable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
    // normally here we would have the QImage buffered up already
    // and would bind as needed, but again, this is the only
    // texture we use for now
    back_texture = bindTexture(QImage(":/gfx/gfx/back.png"));
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    
    glGenBuffers(2, vboid);
    
    glBindBuffer(GL_ARRAY_BUFFER, vboid[0]);
    glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(VertexData), verts, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboid[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4 * sizeof(GLushort), indices, GL_STATIC_DRAW);
    

    }

    void MyGLWidget::paintGL(){
    int texw;
    int texh;
    QMatrix4x4 proj;
    QMatrix2x2 scale;
    quintptr offset;
    int vertexLoc;
    int texcoordLoc;

    texw = (floor(width / ((double) BACK_TILE_S)) + 1);
    texh = (floor(height / ((double) BACK_TILE_S)) + 1);
    
    proj.setToIdentity();
    proj.scale(texw * BACK_TILE_S, texh * BACK_TILE_S);
    proj.ortho(0, width, 0, height, -1, 1);
    
    scale.setToIdentity();
    scale(0,0) = texw;
    scale(1,1) = texh;
    
    default_prog.setUniformValue("texScale", scale);
    default_prog.setUniformValue("mvp_matrix", proj);
    default_prog.setUniformValue("texture", 0);
    
    glBindBuffer(GL_ARRAY_BUFFER, vboid[0]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboid[1]);
    
    offset = 0;
    
    vertexLoc = default_prog.attributeLocation("a_position");
    default_prog.enableAttributeArray(vertexLoc);
    glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void*) offset);
    
    offset += sizeof(QVector3D);
    
    texcoordLoc = default_prog.attributeLocation("a_texcoord");
    default_prog.enableAttributeArray(texcoordLoc);
    glVertexAttribPointer(texcoordLoc, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void*) offset);
    
    glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
    

    }

    void MyGLWidget::resizeGL(int width, int height){
    this->width = width;
    this->height = height;
    }@

    default.vert
    @#version 150

    uniform mat4x4 mvp_matrix;
    uniform mat2x2 texScale;

    in vec4 a_position;
    in vec2 a_texcoord;

    out vec2 v_texcoord;

    void main() {
    v_texcoord = a_texcoord * texScale;
    gl_Position = mvp_matrix * a_position;
    }
    @

    default.frag
    @#version 150

    uniform sampler2D texture;

    in vec2 v_texcoord;

    void main()
    {
    gl_FragColor = texture2D(texture, v_texcoord);
    }
    @


  • Lifetime Qt Champion

    If you are using QOpenGLFunctions you should also use QOpenGLWidget to stay within the same api



  • If only that existed yet :/


  • Lifetime Qt Champion

    Sorry, I've mixed it with something else, I meant QWindow

    You can find an example "here":https://qt-project.org/doc/qt-5.0/qtgui/openglwindow.html


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.