OpenGL and QT, crash at glDrawElements



  • Hi guys,
    I am new here and new to OpenGL ;)

    So I was trying to make something to appear on my screen, but unfortunately it always crashes at glDrawElements.
    I am glad if somebody could help. Here is the code:

    //Initialization 
    void Mesh::initialize()
    {
        this->initializeOpenGLFunctions();
    
        vao = new QOpenGLVertexArrayObject();
        vbo = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
        ebo = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer);
    
        vao->create();
        vbo->create();
        ebo->create();
    
        vao->bind();
    
            vbo->bind();
            vbo->setUsagePattern(QOpenGLBuffer::StaticDraw);
            vbo->allocate(vertices.data(),vertices.size() * sizeof(Vertex)); 
    
    
            ebo->bind(); 
            ebo->setUsagePattern(QOpenGLBuffer::StaticDraw);
            ebo->allocate(indices.data(),indices.size()*sizeof(GLuint)); 
    
    
            //Vertex position
    
            program->enableAttributeArray(0);
            program->setAttributeBuffer(0,GL_FLOAT,0,sizeof(Vertex));
    
            program->enableAttributeArray(1); 
            program->setAttributeBuffer(1,GL_FLOAT,offsetof(Vertex,Normal),3,sizeof(Vertex)); 
    
            glEnableVertexAttribArray(2);
            program->setAttributeBuffer(2,GL_FLOAT,offsetof(Vertex,TextCoords),2,sizeof(Vertex));
    
        vao->release();
    
    }
    

    It always crashes here:

    void Mesh::DrawMesh()
    {
        vao->bind();
        qDebug() << vertices.size();
        glDrawElements(GL_TRIANGLES, indices.size(),GL_UNSIGNED_INT,0);
        vao->release();
    }
    

    Note: When I call vao->isCreated() it returns false even tough I made sure (100%) that initialize() is called BEFORE DrawMesh.

    Here is my Vertex struct:

    struct Vertex
    {
        QVector3D Position;
        QVector3D Normal;
        QVector2D TextCoords;
    };
    

    This is my vertex shader:

    #version 330 core
    
    layout(location=0) in vec3 position;
    layout(location=1) in vec3 normal;
    layout(location=2) in vec2 textCoords;
    
    uniform mat4 MVP;
    
    out vec4 color;
    
    void main(void)
    {
        gl_Position= MVP*vec4(position,1);
        color = vec4(1,1,1,1);
    }
    
    

    Can somebody help me? I'm really stuck here. Also I don't know if I can pass an array of QVector3D like that to the graphicscard...

    Thank you really for your help. ;)



  • Hi, welcome to the Qt forum! Seems like you forgot to create an OpenGL context and make it current, see: http://doc.qt.io/qt-5/qopenglfunctions.html#details

    Edit: There is also a minimal example: http://doc.qt.io/qt-5/qtgui-openglwindow-example.html



  • @Wieland Thanks for the reply Wieland.
    Inside paintGL I loop through a list of meshes and call the DrawMesh() method on all of them. I use a QOpenGLWidget for that.
    So is manually creating a context still the recommended way to go?
    Thanks you ;)



  • @DaOnlyOwner said:

    void Mesh::initialize()

    That should be void Mesh::initializeGL(), in other words override void QOpenGLWidget::initializeGL(). Otherwise the function won't automatically use the correct OpenGL context. May I please see your Mesh header file?



  • @Wieland Of course,

    class Mesh : public QOpenGLFunctions_3_3_Core
    {
    public:
        Mesh(const Mesh& mesh)
        {
            this->vertices = mesh.vertices;
            this->indices = mesh.indices;
            this->program = mesh.program;
            initialize();
        }
    
        Mesh(){}
        ~Mesh()
        {
    
            vao->destroy();
            vbo->destroy();
            ebo->destroy();
    
        }
    
        QVector<Vertex> vertices;
        QVector<GLuint> indices;
        QOpenGLShaderProgram* program;
    
        Mesh(const QVector<Vertex> &vertices, const QVector<GLuint> &indices, QOpenGLShaderProgram* program);
        void DrawMesh();
    
    private:
    
        QOpenGLVertexArrayObject* vao;
        QOpenGLBuffer* vbo;
        QOpenGLBuffer* ebo;
    
        void initialize();
    
    };
    

    The code of my QOpenGLWidget:

    void RenderingWindow::initializeGL()
    {
        this->initializeOpenGLFunctions();    
        program->create();
        program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/testvert.vert" );
        program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/testfrag.frag");
        program->link();
    
        Camera::instance().LookAt(0,0,5, 0,0,0 ,0,1,0);
    }
    
    void RenderingWindow::resizeGL(int w, int h)
    {
        Camera::instance().Perspective(60,w/h,0,10000);
    }
    
    void RenderingWindow::paintGL()
    {
        program->bind();
            program->setUniformValue("MVP",Camera::instance().GetMVP());
            model.Draw();
        program->release();
    }
    
    void RenderingWindow::LoadModel()
    {
        QString filename = QFileDialog::getOpenFileName(this,"Choose Model file",QString(),"Model files (*.fbx *.obj)");
        model.LoadModel(*this, filename, program);
    }
    
    

    model.Draw() goes through all the meshes currently attached to this model and draws them.



  • Mesh(const Mesh& mesh) calls void Mesh::initialize(). Who calls Mesh(const Mesh& mesh)? The constructor must be called from within the correct OpenGL context.



  • @Wieland I think it's called when storing the Meshes inside a QVector. So the constructor is called somewhere in LoadModel().



  • Ok. Then call makeCurrent() in void RenderingWindow::LoadModel().



  • @Wieland somehow It's still not working.
    The reason why I have to call initialize() inside the copyConstructor is, that you can't copy QOpenGLVertexArrayObject..


Log in to reply