1

I'm currently programming an OpenGL ES 2.0 application on both iOS and Android platforms.

In this application I render multiple meshes that all use VBOs. In the process of optimizing the rendering, I realized that the meshes I render share two vertex formats. So I wanted to do the following:

First, setup all vertex attribute pointer offsets, and then simply bind each VBO that uses this vertex format and render it without calling the glVertexAttribPointer function again.

But it gives me strange results.

My question is: Do we have to do the calls glVertexAttribPointer each time we bind a new VBO?

Christian Rau
  • 45,360
  • 10
  • 108
  • 185
F.L.
  • 559
  • 4
  • 11

2 Answers2

2

First of all, like every OpenGL state, the state set with glVertexAttribPointer keeps unchanged until someone else calls glVertexAttribPointer again (for the same attribute index). But the important thing here is, that the internal state changed with glVertexAttribPointer doesn't just store the buffer offset to be used for rendering, offsetting into the VBO bound when calling glDraw.... It also stores the actual buffer object bound when calling glVertexAttribPointer.

So yes, whenever you want your vertex data sourced from another VBO, you need to bind this VBO and do the appropriate glVertexAttribPointer calls while this VBO is bound. While this may seem cumbersome in your case, this is in fact a good thing. This way you don't need to worry about the currently bound buffer when rendering something, but only about the things set up with glVertexAttribPointer. And even more important it let's bind a different VBO before rendering, thus you can source different vertex attributes from different VBOs in a single render call (how else would you do that?).

EDIT: You can however use Vertex Array Objects to ease the process of setting up your vertex data. They encapsulate all the state neccessary for rendering from a bunch of arrays (and thus all the things changed by glVertexAttribPointer, gl(En/Dis)ableVertexAttribArray and the buffer bound to GL_ELEMENT_ARRAY_BUFFER, but like said, not the buffer bound to GL_ARRAY_BUFFER). You still have to properly bind the buffer before calling glVertexAttribPointer of course. But using a VAO you only need this code in some set up routine and all you need to do for rendering is calling glBindVertexArray. Though I don't know if your particular ES device supports them.

Christian Rau
  • 45,360
  • 10
  • 108
  • 185
  • Thanks. This is what I suspected. I'll try to use VAOs, One question is, how efficient is it compared to the classic glBindBuffer-glVertexAttribPointer approach ? – F.L. Jan 30 '13 at 13:11
  • @F.L. It shouldn't have any significant performance impact. In the end a VAO might be slightly more efficient, since you only have to make a single driver call compared to a bunch each time when rendering. But in the end the driver itself will just do the `glVertexAttribPointer` calls internally somehow. But maybe it might even circumvent some sanity checks it has to do when calling `glVertexAttribPointer`, which needn't be done when binding the VAO, of course. But really, in practice VAOs are more about usability than actual perfomance, I think (though it shouldn't be slower than no VAO). – Christian Rau Jan 30 '13 at 13:21
  • What about `glEnableVertexAttribArray` does that need to be reset when swapping VBOs? – nmr Jan 15 '15 at 01:00
  • @nmr No, why should it? It's entirely independent of any buffers, afterall it's just a simple yes/no enable-flag for each individual attribute index, no matter what buffers their actual data will be sourced from, if any at all. – Christian Rau Jan 15 '15 at 01:31
  • Beats me, AFAICT GL state is associated almost at random :) Just trying to figure out what's associated with what. – nmr Jan 15 '15 at 20:29
  • @nmr Well, it isn't too unreasonable if you know the principles. But I agree, there are some places that could use reworking. In fact the whole atttribute stuff is to a large degree indebted to already deprecated things like client arrays (`glVertexAttribPointer`? WTH is a pointer, it's a friggin buffer), but that also got reworked recently (some 4.x so to say) with a new way of associating buffers to attributes and separating the actual buffer from the format. – Christian Rau Jan 15 '15 at 20:35
1

Some cool resource I found on drawing with VAO / VBO

http://www.arcsynthesis.org/gltut/Positioning/Tutorial%2005.html#d0e4720

It shows how you can drive several objects, with several VAOs and a single VBO for example (each VAO holding pointers with different offsets to the same VBO)

Definitively worth a look, not mentioning the part where you learn that

  • glBindBuffer(GL_ARRAY_BUFFER...doesn't bind any data, it's just a global pointer for the following glVertexAttribPointer calls which do the actual data binding

BUT

  • glBindBuffer(GL_ELEMENT_ARRAY_BUFFER...DOES bind/save the element array into the current VAO
Vinzzz
  • 11,746
  • 5
  • 36
  • 42