A Vertex Buffer Object (VBO for short) is an extension developed by the ARB board to buffer data to VRAM so as to make rendering faster. This is similar to display lists in which the display list is cached in VRAM and executed from there, yielding a higher FPS. This tutorial is meant to provide a simple introduction to using VBOs.
Vertex Buffer objects differ from display lists, they differ in the sense that display lists cannot be modified dynamically and once the display lists is compiled, you would have to generate a new display list, delete the old one so that the new data can be sent to the card. VBOs have 3 different flavours, static, dynamic and stream, the latter two are designed to handle dynamic data such as animation. However, various reports and benchmarks on the internet show that display lists are faster than static VBOs by a small margin, but the advantages of using VBOs definetly outweigh the disadvantages.
The official name for the extension is GL_ARB_vertex_buffer_object and the class that represents that extension is org.lwjgl.opengl.ARBVertexBufferObject. It is relatively easy to use and should give your game a solid FPS increase if that extension is supported by the vendor's card. This extension relies heavily on vertex arrays and you should be familar with vertex arrays before reading this tutorial.
It is relatively easy to generate a VBO id, much like a Texture id:
public static int createVBOID() { if (GLContext.getCapabilities().GL_ARB_vertex_buffer_object) { IntBuffer buffer = BufferUtils.createIntBuffer(1); ARBVertexBufferObject.glGenBuffersARB(buffer); return buffer.get(0); } return 0; }
That ID is important, your going to need it when rendering (again, much like a texture id). To buffer the data to VRAM (or whatever your driver feels approperiate), you do this:
public static void bufferData(int id, FloatBuffer buffer) { if (GLContext.getCapabilities().GL_ARB_vertex_buffer_object) { ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, id); ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, buffer, ARBVertexBufferObject.GL_STATIC_DRAW_ARB); } } public static void bufferElementData(int id, IntBuffer buffer) { if (GLContext.getCapabilities().GL_ARB_vertex_buffer_object) { ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, id); ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, buffer, ARBVertexBufferObject.GL_STATIC_DRAW_ARB); } }
There are two GLEnums that are new up there, GL_ARRAY_BUFFER_ARB and GL_STATIC_DRAW_ARB. The first is a buffer type to store vertex information, normals, colours and texture coordinates. There is another type which stores indices and thats GL_ELEMENT_ARRAY_BUFFER_ARB, use both to get the optimum speed from VBOs. Also, consider making your data interleaved and using the strides and offsets to get maximum VBO speed as interleaved data only needs 1 VBO id and thus can be managed easier by the GL driver.
The second GLEnum: GL_STATIC_DRAW_ARB has a couple of other relatives, the important ones are GL_DYNAMIC_DRAW_ARB and GL_STREAM_DRAW_ARB, both of which are outside the scope of this tutorial.
Now that you have generated and and stored the VBO id, you can render:
public static void render() { GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY); ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, vertexBufferID); GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0); GL11.glEnableClientState(GL11.GL_COLOR_ARRAY); ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, colourBufferID); GL11.glColorPointer(4, GL11.GL_FLOAT, 0, 0); ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, indexBufferID); GL12.glDrawRangeElements(GL11.GL_TRIANGLES, 0, maxIndex, indexBufferSize, GL11.GL_UNSIGNED_INT, 0); }
The above code is optimal for static meshes (hence the GL_STATIC_DRAW_ARB), so for models, you might want to investigate GL_DYNAMIC_DRAW_ARB or GL_STREAM_DRAW_ARB. There also methods for reading back the data in the VBO.