Maxim Blinov
Maxim Blinov

Reputation: 946

Qt 5.5 and OpenGL: read access violation exception raised when trying to call paintGL()

I am writing a simple application that uses Qt 5.5 and OpenGL to draw some very basic geometry in a QtOpenGLWidget. Initially, much of the vertex data initialization and rendering code was taken out of a tutorial designed to draw a single triangle. This version worked correctly, but my own attempt at modifying it to facilitate 4 vertices to form a square has underwent without success. The program compiles with no errors, but crashes when executed without even drawing the ui to the screen, with the following error:

error: Exception at 0x53fe35, code: 0xc0000005: read access violation at: 0x0, flags=0x0 (first chance)

I am using Qt's OpenGL wrappers everywhere I can.

The first potential (and probable) solution I found is in this post; the problem in question has an identical error signature, and the description of the cause of the problem, that being incorrectly enabled or configured VAO's, also seems considerable to my case, considering the addition of another vertex to the VBO and my likely ineptitude to correctly reconfigure the glVertexAttribPointer. I cannot, however, find the problem in my code.

GLWidget's (the OpenGL widget in question) declaration:

class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions {
    Q_OBJECT

    void prepareVertexBuffers();

    void prepareVertexShader();
    void prepareFragmentShader();
    void prepareShaderProgram();

    void applyShaderPrograms();

    QOpenGLBuffer *vertBuffer;
    QOpenGLBuffer *elementBuffer;
    QOpenGLVertexArrayObject *vao;

    QOpenGLShader *vertShader;
    QOpenGLShader *fragShader;
    QOpenGLShaderProgram *shaderProgram;

public:
    GLWidget(QWidget *parent = 0);

    void initializeGL();
    void resizeGL();
    void paintGL();

signals:
    void shaderCompiled(const QString compilationLog);

public slots:
    void updateFragmentShader(QString newsource);
};

prepareVertexBuffers() function - here I define 4 vertices and arrange them into 2 triangles to form a square.

void GLWidget::prepareVertexBuffers() {

    static const GLfloat vertData[] = {
       -1.0f, 1.0f, 0.0f,
       -1.0f, -1.0f, 0.0f,
       1.0f,  -1.0f, 0.0f,
       1.0f,  1.0f, 0.0f,
    };

    static const GLushort elementData[] = {1, 2, 3, 2, 3, 4};

    vao = new QOpenGLVertexArrayObject(this);
    vao->create();
    vao->bind();

    vertBuffer = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
    vertBuffer->create();
    vertBuffer->allocate(vertData, 4 * 3 * sizeof(GLfloat) );
    vertBuffer->setUsagePattern( QOpenGLBuffer::StaticDraw );
    vertBuffer->bind();

    elementBuffer = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer);
    elementBuffer->create();
    elementBuffer->allocate(elementData, 6 * sizeof(GLushort) );
    elementBuffer->setUsagePattern( QOpenGLBuffer::StaticRead );
    elementBuffer->bind();
}

paintGL(), where I suspect the problem is:

void GLWidget::paintGL() {
    vao->bind();
    vertBuffer->bind();
    elementBuffer->bind();

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, (void*)0 );
    glEnableVertexAttribArray(0);

    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glDrawArrays(GL_TRIANGLES, 0, 4);
    glDisableVertexAttribArray(0);
    elementBuffer->release();
    vertBuffer->release();
    vao->release();
}

It is obvious to note that I have virtually no experience in using OpenGL, and so clues as to how to structure my code correctly and general coding practices would also be appreciated.

Upvotes: 0

Views: 1518

Answers (1)

Maxim Blinov
Maxim Blinov

Reputation: 946

Thanks derhass for some clarification. I blindly assumed that glDrawArrays magically uses the currently bound element buffer to draw - evidently it is not so. I change the line

glDrawArrays(GL_TRIANGLES, 0, 4);

to

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);

and the program no longer crashes on startup.

Furthermore, I made sure to bind() the buffers before allocating memory to them as per the documentation.

Upvotes: 0

Related Questions