1
votes

I am having trouble understanding how to use VAO's in OpenGL ES2 (on iOS) and getting them to work. My current rendering setup looks like this (in pseudocode):

Initialization:

foreach VBO:
    glGenBuffers();

Rendering a frame:

// Render VBO 1
glClear(color | depth);
glBindBuffer(GL_ARRAY_BUFFER, arrayVBO1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBO1);
foreach vertex attribute:
    glVertexAttribPointer();
    glEnableVertexAttribArray();
glBufferData(GL_ARRAY_BUFFER, ...);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, ...);
glDrawElements(GL_TRIANGLE_STRIP, ...);

// Render VBO 2
glClear(color | depth);
glBindBuffer(GL_ARRAY_BUFFER, arrayVBO2);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBO2);
foreach vertex attribute:
    glVertexAttribPointer();
    glEnableVertexAttribArray();
glBufferData(GL_ARRAY_BUFFER, ...);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, ...);
glDrawElements(GL_TRIANGLE_STRIP, ...);

This works fine, however, both VBO's have exactly the same interleaved vertex attribute struct, and as you can see I'm setting up and enabling each attribute every frame for every VBO. Instruments complains about redundant calls to glVertexAttribPointer() and glEnableVertexAttribArray(), but when I move one of them or both to the initialization phase I either get a EXC_BAD_ACCESS when calling glDrawElements or nothing is drawn.

My question is whether I need to do this every frame, why it doesn't work if I don't, and how I would use VAO's to solve this.

1
Are you calling glBufferData in the middle of rendering? Admittedly, I don't work on mobile platforms or ES-2.0, but I can't imagine how that could possibly be a good idea. Buffer objects retain their data until explicitly told to contain other data. It's like calling malloc followed by memcpy every frame just to hand someone an array. You do it once, then just keep handing them the one array you allocated.Nicol Bolas
I do this for dynamic data, for static data I buffer it once and draw it every frame.Jonesy
I ran into this exact same issue, and was unable to resolve it. I keep getting 1282 (GL_INVALID_OPERATION) when using the VAO, but the exact same commands (glBindBuffer, glEnableVertexAttribArray, glVertexAttribPointer), work find when not using a VAO. I am starting to conclude that VAO's do not seem to work for Vertex Buffers when using interleaved arrays on iOS. Or I am missing something really small but crucial.bobobobo

1 Answers

0
votes

Sorry for the dredge, but I'm procrastinating and you keep topping my google search. I'm sure you've solved it by now...

The correct way is to only update the buffers when the data changes, not every frame. Ideally, you would only update the part of the buffer that changed. Also, Attribute Pointers are offsets into the buffer if a buffer is bound.

Initialisation:

glGenBuffers()
foreach VBO:
   glBufferData()

Updates / Animation, etc:

glMapBuffer() //or something like this
buffer->vertex = vec3(1,2,3) // etc
glUnmapBuffer()

And Render:

glBindFBO()
glClear(color | depth);

glBindBuffer(GL_ARRAY_BUFFER, arrayVBO1)
glVertexAttribPointer(GL_VERTEX,..., 0) // Buffer Offset = 0
glVertexAttribPointer(GL_TEXCOORD,..., sizeof(vertex)) // Buffer Offset = size of vertex

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBO1);
glEnableVertexAttribArray(..., 0) // Buffer Offset = 0

glBindBuffer(0); // Unbind buffers, you don't need them here
glDrawElements(GL_TRIANGLE_STRIP, ...);

Hope that helps.