0

I am trying to combine a vertex array object with a vertex buffer & an index buffer using Qt.

The following code combines a VAO and a VBO, working perfectly:

// Create buffers
void Tile::setupBuffers() {
    vbo.create();
    vbo.bind();
    vbo.setUsagePattern(QOpenGLBuffer::StaticDraw);
    vbo.allocate(vertices.constData(), vertices.size() * sizeof(QVector3D));
    vbo.release();

    vao.create();

    shaderProgram->bind();
    vao.bind();
        vbo.bind();
        shaderProgram->enableAttributeArray(0);
        shaderProgram->setAttributeBuffer(positionLocation, GL_FLOAT, 0, 3, 0);    
    vao.release();

    shaderProgram->disableAttributeArray(0);
    vbo.release();
    shaderProgram->release();
}

// Draw triangle    
void Tile::draw() {
    shaderProgram->bind();
    vao.bind();

    glDrawArrays(GL_TRIANGLES, 0, 3);

    vao.release();
    shaderProgram->release();
}

When I'm now trying to add an index buffer nothing gets drawn except for the clear color. Here's the code:

// Create buffers
void Tile::setupBuffers() {
    vbo.create();
    vbo.bind();
    vbo.setUsagePattern(QOpenGLBuffer::StaticDraw);
    vbo.allocate(vertices.constData(), vertices.size() * sizeof(QVector3D));
    vbo.release();

    ibo.create();
    ibo.bind();
    ibo.setUsagePattern(QOpenGLBuffer::StaticDraw);
    ibo.allocate(indices.constData(), indices.size() * sizeof(GLushort));
    ibo.release();

    vao.create();

    shaderProgram->bind();
    vao.bind();
        vbo.bind();
        shaderProgram->enableAttributeArray(0);
        shaderProgram->setAttributeBuffer(positionLocation, GL_FLOAT, 0, 3, 0);

        ibo.bind();
    vao.release();

    shaderProgram->disableAttributeArray(0);
    vbo.release();
    ibo.release();
    shaderProgram->release();
}

void Tile::draw() {
    shaderProgram->bind();
    vao.bind();

    glDrawElements(GL_TRIANGLES, 3, GL_FLOAT, 0);

    vao.release();
    shaderProgram->release();
}

Here's the content of my vertex vector & index vector:

vertices = {
    QVector3D(1.0f, -1.0f, 0.0f),
    QVector3D(1.0f, 1.0f, 0.0f),
    QVector3D(-1.0f, -1.0f, 0.0f)
};

indices = {
     0, 1, 2
};

I assume the order of binding the VAO/VBO/IBO in the second code block is wrong, I just don't know how it's done right. Any help is appreciated.

vigilanum
  • 133
  • 1
  • 5
  • 1
    Is there any actual OpenGL in this, or are you just using some kind of wrapper for all of this? – Nicol Bolas Jun 23 '16 at 18:55
  • I use the wrappers provided by Qt: http://doc.qt.io/qt-5/qopenglvertexarrayobject.html http://doc.qt.io/qt-5/qopenglbuffer.html – vigilanum Jun 23 '16 at 18:57
  • ... wow. Qt's wrapper is *garbage*. I can't tell what's worse: that they made `setAttributeBuffer` a member of a type that has *absolutely* nothing to do with vertex state, or that they didn't even bother to let you pass a buffer object *directly* to it, which is [the very worst aspect of `glVertexAttribPointer`](http://stackoverflow.com/q/37972229/734069). I'm impressed; it takes genuine effort to screw up *that badly*. – Nicol Bolas Jun 23 '16 at 19:08
  • @NicolBolas: yes, unfortunately `QOpenGLShaderProgram` tried to be a bit "too smart" by providing convenience methods for location lookup + vertex buffer specification. (It also has many other drawbacks but let's not get there now). It does not make any sense to have those methods there. OTOH I can see why there isn't exactly a "better" place to put them -- VAOs come to mind, but there are no VAOs in GL2 or GLES2, and `QOGLSP` as you can imagine predates `QOGLVAO`. :-\ – peppe Jun 23 '16 at 23:05

1 Answers1

3
glDrawElements(GL_TRIANGLES, 3, GL_FLOAT, 0);

Your indices are GLushorts, not floats. You should have gotten a GL_INVALID_ENUM error; you should always check for GL errors.

Also, shaderProgram->disableAttributeArray(0); is completely unnecessary. The enable/disable state is part of the VAO (Qt's idiotic wrapper to the contrary). Disabling the attribute won't change the VAO, since you unbound it. And you don't want to disable it anyway.

Lastly, there's this:

shaderProgram->enableAttributeArray(0);
shaderProgram->setAttributeBuffer(positionLocation, GL_FLOAT, 0, 3, 0);

The first parameter of both of these functions should be the same. They probably are, so this is more of a benign bug. But it's still wrong.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Thanks, now the drawing works. If I didn't have to use Qt, I wouldn't, on that you can be sure. – vigilanum Jun 23 '16 at 19:29
  • 2
    @vigilanum: You *don't* have to use Qt's wrappers. You can use Qt to create the window and use direct OpenGL calls to render to it. – Nicol Bolas Jun 23 '16 at 19:30
  • Well, I have to because the assignment dictates that. – vigilanum Jun 23 '16 at 19:43
  • @vigilanum At the most basic level, Qt gives you resolved function pointers to GL wrapped into trivial methods. You don't need to use any higher level of abstraction unless that is specifically dictated by the assignment. – Kuba hasn't forgotten Monica Jun 24 '16 at 00:05