I’ve been dabbling in graphics programming a bit, mostly OpenGL glBegin/glEnd schtuff lately. A friend pointed me to vertex buffer objects (VBO’s) as a better alternative, so I decided to learn a bit about them. That said, I couldn’t find a tutorial that suited my needs, so I thought I’d offer one here.
First off, there are tutorials out there, just not what I need/want. Let me list them.
- NeHe, purveyor of all things graphical has a great tutorial (#45), that I even used as a reference for mine.
The problem for me was that it came with way more than what I wanted to learn at this point (heightmaps and the like), and I just wanted a focused example on VBO’s without having to worry about setting everything up “just right”.
- DevMaster, my surrogate home, had a decent tutorial that was brief (here), but had various errors and didn’t compile out of the box. It also didn’t work, at least not for me!
So here I decided to cobble together a working demo (once I figured out how), and post it up for all the world to see.
Now keep in mind a few things about this:
1.- I might have my terminology messed up. I keep hearing people refer to this as DrawArrays, Vertex Buffer Objects, Vertex Array something-or-other, etc. If someone can clear this up for me, I’d be happy to hear from you.
2.- I don’t do a lot of error checking in this demo. It’s definitely bad practice, but I wanted to keep things brief. There’s a couple of comments in there noting where I should be, and there might be a few places that I should mention these things.
Anyhow, without further ado, here’s the demo. I hope it helps someone.
- /**
- * Vertex Buffer Objects (herein after referred to as VBOs) demo.
- *
- * Author: Eddie Parker
- * www.kickingdragon.com
- *
- * This demo is a really simple example of how to use VBOs [1].
- *
- * Why would you use VBOs? Because the data is uploaded an manipulated
- * on the graphics card RAM instead of system RAM, therefore it's faster,
- * and doesn't clog up your BUS, and keeps your whites whiter.
- *
- * [1] http://steinsoft.net/index.php?site=Programming/Code%20Snippets/OpenGL/no11
- *
- */
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #include <SDL/SDL.h>
- #include <SDL/SDL_main.h>
- #include <GL/gl.h>
- #include <GL/glu.h>
- /**
- * glext.h snippet
- *
- * glext.h isn't always found in people's distributions.
- * I've copied the parts we need here -- if you have it available,
- * it would be better to include it directly.
- *
- * Basically, we have a couple of defines that are used later on for
- * glBindBufferARB and glBufferDataARB calls, as well as typedefs
- * that specify the function signatures for the functions we plan on using.
- *
- * Why do we need the typedefs?
- *
- * Quite simply, because the OpenGL Architecture Review Board (ARB) has
- * created these functions as 'extensions' - that is, they're not part
- * of the 'official' library, and therefore might or might not be
- * available. At runtime, it's necessary to crack open the OpenGL
- * DLL and retrieve the function pointers, assign them, and
- * then we're able to use them in our application.
- *
- * For more information, see [1].
- *
- * [1] http://www.opengl.org/resources/faq/technical/extensions.htm
- */
- #define GL_ARRAY_BUFFER_ARB 0x8892
- #define GL_STATIC_DRAW_ARB 0x88E4
- typedef void (APIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
- typedef void (APIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
- typedef void (APIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);
- typedef void (APIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, int size, const GLvoid *data, GLenum usage);
- /**
- *
- * END glext.h snippet
- *
- */
- /**
- * Allocate four function pointers on the data segment so we can assign to them later,
- * if we have them available.
- */
- PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;
- PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;
- PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL;
- PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL;
- /**
- * Initialization function to set up our requisite libraries.
- */
- int Initialize()
- {
- SDL_Init(SDL_INIT_VIDEO);
- SDL_SetVideoMode(640, 480, 32, 2);
- //! @TODO: I should check for the availability of DrawArrays and
- // check for failure to load these functions.
- glBindBufferARB = (PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB");
- glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffersARB");
- glBufferDataARB = (PFNGLBUFFERDATAARBPROC)wglGetProcAddress("glBufferDataARB");
- }
- int main(int argc, char **argv)
- {
- // Setup our required libraries.
- Initialize();
- // Set up OpenGL
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- // Initialize a perspective.
- gluPerspective(45.f, 640.f / 480.f, 1.f, 512.f);
- // Set our clear colour to black
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- // Set up a purdy triangle as our vertex data.
- GLfloat vertexData[] = { 0.f, 1.f, 0.f
- , -1.f, -1.f, 0.f
- , 1.f, -1.f, 0.f
- };
- // Set a lovely teal with some Gouraud shading for
- // our triangle.
- GLfloat colourData[] = { 0.f, 0.f, 1.f
- , 0.f, 1.f, 1.f
- , 1.f, 1.f, 1.f
- };
- // Create some 'ids' for the buffers.
- GLuint vertexBuffer = 0;
- GLuint colourBuffer = 0;
- // 1.- Generated a buffer name for our vertex buffer,
- glGenBuffersARB(1, &vertexBuffer);
- // 2.- Set our current 'in-use' buffer to our vertex buffer.
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
- // 3.- Fill out the data buffer using our initialized values.
- glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertexData), vertexData, GL_STATIC_DRAW_ARB);
- // Same as steps 1, 2 and 3 above, but using colour data.
- glGenBuffersARB(1, &colourBuffer);
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, colourBuffer);
- glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(colourData), colourData, GL_STATIC_DRAW_ARB);
- // Initialize the ability to use vertex arrays and colour arrays.
- // I should really be making sure I have this capability and use
- // glIsEnabled first.
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
- bool bRunning = true;
- SDL_Event event;
- while (bRunning)
- {
- if(SDL_PollEvent(&event))
- {
- if(event.key.keysym.sym == SDLK_ESCAPE)
- {
- bRunning = false;
- continue;
- }
- }
- // Clear our depth buffer and color bit
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- // Reset our view
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- // Move back a bit to see our triangle in it's glory.
- glTranslatef(0, 0, -5);
- // --- VBO's in action.
- // Set the vertexBuffer as the current buffer.
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
- // Specify that it's data is vertex data.
- glVertexPointer(3, GL_FLOAT, 0, 0);
- // Set the colourBuffer as the current buffer.
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, colourBuffer);
- // Specify that it's data is colour data.
- glColorPointer (3, GL_FLOAT, 0, 0);
- // Tell OpenGL to draw what it sees. ;)
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
- // --- End VBO's in action.
- // Swap buffers!
- SDL_GL_SwapBuffers();
- }
- // Disable the client states.
- glDisableClientState( GL_VERTEX_ARRAY );
- glDisableClientState( GL_COLOR_ARRAY );
- //!TODO: Free the buffers created in glBufferDataARB
- return 0;
- }
16 Comments »
RSS feed for comments on this post. TrackBack URI
Leave a comment

Pingback by codepixel - Vertex Buffer Objects — January 14, 2008 #
I’ve been struggling for ages trying to get VBO’s working. All I needed was a simple demo that works to show me exactly how its done without all the extra bits often seen in other demos.
I now have a working program that I can make modifications to so thanks very much for a useful resource.
Comment by Lynton — January 22, 2008 #
I know what you mean, Lynton. I find I need to grasp a concept in small terms so I can put it to good use in a much larger project.
Glad my little code snippet could help!
Comment by eddie — January 22, 2008 #
Pingback by OpenGL vertex buffer objects tutorial (://URLFAN) — June 24, 2008 #
doesn’t fucking work
Comment by dipshit — August 10, 2008 #
Feel free to tell me what your error is, previous poster, and I’ll see if I can help you.
Granted, feel free to omit the swearing.
Comment by eddie — August 11, 2008 #
Everything is in lower case! People are going to be in for a surprise if they copy-paste it and try to compile it.
Comment by Glenn — September 8, 2008 #
Oops! Good catch Glenn. I’ve fixed the CSS code to stop transforming it to the lower case. Should be better now.
Comment by eddie — September 9, 2008 #
Thank you very very much for that, i was looking for a VBO tutorial and all of them were either too complex or not good enough. That tutorial is what i was looking for.
Comment by revani — October 7, 2008 #
Pingback by Are Virtual Function Calls Still Expensive? | The Coffeehouse | Channel 9 — December 22, 2008 #
Pingback by VertexBufferObjects problem. - DevMaster.net Forums — April 8, 2009 #
Pingback by VBOs in OpenGL (using Tao framework, if that matters) — October 31, 2009 #
Thanks. Your tutorial really helped just because it is so simple. All the other tutorial I’ve looked at had indexed or interleaved arrays that made things much more complicated and harder to understand. This one is simple and therefore great.
Comment by Nauris — May 20, 2010 #
Pingback by Inside3d Forums :: View topic - Not exactly related to quake but VBO's — December 1, 2010 #
Really simple thank you. Converted to win32 but core is the same and works 100%. Still valid after all this time
Comment by Gavin Simpson — July 25, 2011 #
Pingback by [OpenGL] Problem z wy¶wietlaniem obiektów za pomoc± VBO - theModders — October 29, 2011 #