VBOs and IBOs - the real difference


I was just coding a simple manager for my buffer objects and I have found something that I find interesting. Let’s create an IBO:

glGenBuffers(1, &bufferObject);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferObject);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof([b]arrVertexBuffer[/b]), [b]arrVertexBuffer[/b], GL_STATIC_DRAW);

That’s right - I am creating an IBO, but fill it with vertex data.
Now let’s draw something:

[b]glBindBuffer(GL_ARRAY_BUFFER, bufferObject);[/b]
// Some code...
glDrawArrays(GL_TRIANGLES, 0, vertexCount);

I was a bit surprised that it worked. I checked it on Windows 7 with nVidia card (OpenGL 2.0) and Android 2.3.6 (GLES 2.0).

So my questions are:

  1. Can I legally create a buffer as IBO and then use it as VBO (and vice versa)?
  2. If yes, then I guess that IBOs and VBOs, at the moment of their creation, are in fact the same thing. So why do we need to pass the target to glBufferData? Wouldn’t passing a buffer object name be more intuitive?

Sorry for those noob questions, but I find it interesting and I couldn’t find an answer anywhere. Everyone is saying just “create buffer as VBO and use it as VBO” (even the OpenGL standard document), so I was hoping to get some information here. :slight_smile:

I believe that drivers may or may not make optimizations to the buffer’s storage depending on the parameters used in the first glBufferData call, so while you can bind a buffer object as a different type and use it as if it were that type (try it with PBOs now - you can do that too) it may or may not be suboptimal.

All implementation-dependent, of course.

As for the design of glBufferData, and why it doesn’t get the buffer object name, this is all historical gunk rooted in design decisions made when OpenGL was young but which can seem borderline-insane these days, and a bad initial specification of buffer objects (which needed to be patched by a few extensions to make them actually usable in real-world programs).

As far as OpenGL is concerned, a buffer object is a buffer object. There is no such thing as a vertex buffer object or an index buffer object or anything else. There is a buffer object, which is a linear array of GPU-controlled memory that you can allocate. And you can use that buffer object for many different things.

So you may use a buffer object for both vertex and element/index data. You can also use the same one for pixel transfers, transform feedback, and even uniforms.

That being said, it’s best not to confuse the OpenGL implementation. Using the same buffer for vertex and element data is fine. As is using that buffer for transform feedback. But once you start throwing uniforms into that, you may find that things have slowed down somewhat.

As stated in the linked article, OpenGL implementations are allowed to make optimizations based on the location that a buffer object is first bind to.

Everyone is saying just “create buffer as VBO and use it as VBO” (even the OpenGL standard document)

It most certainly does not. The OpenGL standard never uses the terms “VBO”, “vertex buffer object”, or anything of the kind.

Great, that’s exactly what I wanted to know. Thank you for your replies. :slight_smile: