3
\$\begingroup\$

From my understanding of what glBindVertexArray does and how it works, the following code should work fine:

First init:

    glGenVertexArraysOES(1, &_vertexArray);
    glBindVertexArrayOES(_vertexArray);

    glGenBuffers(1, &_buffer);
    glBindBuffer(GL_ARRAY_BUFFER, _buffer);
    glBufferData(GL_ARRAY_BUFFER, kMaxDrawingVerticesCount*sizeof(GLKVector3), NULL, GL_DYNAMIC_DRAW);

    glGenBuffers(1, &_indexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, kMaxDrawingVerticesCount*1.5*sizeof(GLuint), NULL, GL_DYNAMIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLKVector3), BUFFER_OFFSET(0));

    glBindVertexArrayOES(0);

And later add new geometry:

glBindVertexArrayOES(_vertexArray);
glBufferSubData(GL_ARRAY_BUFFER, 0, (GLintptr)_data.vertices.length, _data.vertices.bytes);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, (GLintptr)_data.indices.length, _data.indices.bytes);
glBindVertexArrayOES(0);

However, it doesn't work (there is screen output, but it looks like the buffers were changed between each other). Binding the vertex array is not enough for the vertex/indices buffer to get bound? Because, if I do this:

glBindVertexArrayOES(_vertexArray);
glBindBuffer(GL_ARRAY_BUFFER, _buffer); <-- note this line
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); <-- note this line

glBufferSubData(GL_ARRAY_BUFFER, 0, (GLintptr)_data.vertices.length, _data.vertices.bytes);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, (GLintptr)_data.indices.length, _data.indices.bytes);
glBindVertexArrayOES(0);

Everything works/looks as expected. I find it strange, since the vertex array should have taken care of the buffer binding. Otherwise, what's the purpose to have a vertex array if you still have to bind all the buffers?

\$\endgroup\$

3 Answers 3

4
\$\begingroup\$

The behavior you're seeing is correct. Consider the case where you're using two vertex streams:

glBindVertexArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 1);
glVertexAttribPointer(...);
glBindBuffer(GL_ARRAY_BUFFER, 2);
glVertexAttribPointer(...);
glBindVertexArray(0);

Now what? The VAO was designed to store whole arrays of bindings, specifically for drawing. It can't substitute for buffer binding semantics in functions that modify buffer state, because it's not clear which buffer should be bound. The first? The last?

Bind the VAO to draw. Bind the VBO to modify the VBO.

\$\endgroup\$
1
  • \$\begingroup\$ Makes perfect sense, thank you so much for making this clear. \$\endgroup\$
    – Meda
    Feb 20, 2013 at 23:36
1
\$\begingroup\$
glBindBuffer(GL_ARRAY_BUFFER, _buffer); <-- note this line

What about it? As has been stated many, many times before, the association between a buffer object and a vertex array is made by glVertexAttribPointer, not by glBindBuffer. Therefore, if you want to change that association, you must bind the buffer and call glVertexAttribPointer. Because that is what gets stored in the VAO.

\$\endgroup\$
0
0
\$\begingroup\$

If you're having errors, maybe this

glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, (GLintptr)_data.indices.length, _data.indices.bytes);

is incorrect. glBufferSubData requires size in bytes. You haven't allocated the buffer size explicitly as bytes so i'm guessing that sending just the length is not intentional.

EDIT:

Another thing is, you're using OpenGL ES2 and AFAIK it doesn't have VAOs, is that an extension? Are you sure that it's working properly?

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .