OpenGL vertex buffer objects tutorial
rss

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.

  1. /**
  2.   * Vertex Buffer Objects (herein after referred to as VBOs) demo.
  3.   *
  4.   * Author: Eddie Parker
  5.   * www.kickingdragon.com
  6.   *
  7.   * This demo is a really simple example of how to use VBOs [1].
  8.   *
  9.   * Why would you use VBOs? Because the data is uploaded an manipulated
  10.   * on the graphics card RAM instead of system RAM, therefore it's faster,
  11.   * and doesn't clog up your BUS, and keeps your whites whiter.
  12.   *
  13.   * [1] http://steinsoft.net/index.php?site=Programming/Code%20Snippets/OpenGL/no11
  14.   *
  15.   */
  16.  
  17. #define WIN32_LEAN_AND_MEAN
  18. #include <windows.h>
  19.  
  20. #include <SDL/SDL.h>
  21. #include <SDL/SDL_main.h>
  22. #include <GL/gl.h>
  23. #include <GL/glu.h>
  24.  
  25. /**
  26.   * glext.h snippet
  27.   *
  28.   * glext.h isn't always found in people's distributions.
  29.   * I've copied the parts we need here -- if you have it available,
  30.   * it would be better to include it directly.
  31.   *
  32.   * Basically, we have a couple of defines that are used later on for
  33.   * glBindBufferARB and glBufferDataARB calls, as well as typedefs
  34.   * that specify the function signatures for the functions we plan on using.
  35.   *
  36.   * Why do we need the typedefs?
  37.   *
  38.   * Quite simply, because the OpenGL Architecture Review Board (ARB) has
  39.   * created these functions as 'extensions' - that is, they're not part
  40.   * of the 'official' library, and therefore might or might not be
  41.   * available. At runtime, it's necessary to crack open the OpenGL
  42.   * DLL and retrieve the function pointers, assign them, and
  43.   * then we're able to use them in our application.
  44.   *
  45.   * For more information, see [1].
  46.   *
  47.   * [1] http://www.opengl.org/resources/faq/technical/extensions.htm
  48.   */
  49. #define GL_ARRAY_BUFFER_ARB 0x8892
  50. #define GL_STATIC_DRAW_ARB 0x88E4
  51. typedef void (APIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
  52. typedef void (APIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
  53. typedef void (APIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);
  54. typedef void (APIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, int size, const GLvoid *data, GLenum usage);
  55. /**
  56.   *
  57.   * END glext.h snippet
  58.   *
  59.   */
  60.  
  61. /**
  62.   * Allocate four function pointers on the data segment so we can assign to them later,
  63.   * if we have them available.
  64.   */
  65. PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;
  66. PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;
  67. PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL;
  68. PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL;
  69.  
  70. /**
  71.   * Initialization function to set up our requisite libraries.
  72.   */
  73. int Initialize()
  74. {
  75.     SDL_Init(SDL_INIT_VIDEO);
  76.     SDL_SetVideoMode(640, 480, 32, 2);
  77.    
  78.     //! @TODO: I should check for the availability of DrawArrays and
  79.     // check for failure to load these functions.
  80.     glBindBufferARB = (PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB");
  81.     glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffersARB");
  82.     glBufferDataARB = (PFNGLBUFFERDATAARBPROC)wglGetProcAddress("glBufferDataARB");
  83. }
  84.  
  85. int main(int argc, char **argv)
  86. {
  87.     // Setup our required libraries.
  88.     Initialize();
  89.    
  90.     // Set up OpenGL
  91.     glMatrixMode(GL_PROJECTION);
  92.     glLoadIdentity();
  93.    
  94.     // Initialize a perspective.
  95.     gluPerspective(45.f, 640.f / 480.f, 1.f, 512.f);
  96.    
  97.     // Set our clear colour to black
  98.     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  99.    
  100.     // Set up a purdy triangle as our vertex data.
  101.     GLfloat vertexData[] =    { 0.f, 1.f, 0.f
  102.                             , -1.f, -1.f, 0.f
  103.                             , 1.f, -1.f, 0.f
  104.                             };
  105.    
  106.     // Set a lovely teal with some Gouraud shading for
  107.     // our triangle.
  108.     GLfloat colourData[] =    { 0.f, 0.f, 1.f
  109.                             , 0.f, 1.f, 1.f
  110.                             , 1.f, 1.f, 1.f
  111.                             };
  112.    
  113.     // Create some 'ids' for the buffers.
  114.     GLuint vertexBuffer = 0;
  115.     GLuint colourBuffer = 0;
  116.    
  117.     // 1.- Generated a buffer name for our vertex buffer,
  118.     glGenBuffersARB(1, &vertexBuffer);
  119.    
  120.     // 2.- Set our current 'in-use' buffer to our vertex buffer.
  121.     glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
  122.    
  123.     // 3.- Fill out the data buffer using our initialized values.
  124.     glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertexData), vertexData, GL_STATIC_DRAW_ARB);
  125.    
  126.     // Same as steps 1, 2 and 3 above, but using colour data.
  127.     glGenBuffersARB(1, &colourBuffer);
  128.     glBindBufferARB(GL_ARRAY_BUFFER_ARB, colourBuffer);
  129.     glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(colourData), colourData, GL_STATIC_DRAW_ARB);
  130.    
  131.     // Initialize the ability to use vertex arrays and colour arrays.
  132.     // I should really be making sure I have this capability and use
  133.     // glIsEnabled first.
  134.     glEnableClientState(GL_VERTEX_ARRAY);
  135.     glEnableClientState(GL_COLOR_ARRAY);
  136.    
  137.     bool bRunning = true;
  138.     SDL_Event event;
  139.    
  140.     while (bRunning)
  141.     {
  142.         if(SDL_PollEvent(&event))
  143.         {
  144.             if(event.key.keysym.sym == SDLK_ESCAPE)
  145.             {
  146.                 bRunning = false;
  147.                 continue;
  148.             }
  149.         }
  150.        
  151.         // Clear our depth buffer and color bit
  152.         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  153.        
  154.         // Reset our view
  155.         glMatrixMode(GL_MODELVIEW);
  156.         glLoadIdentity();
  157.        
  158.         // Move back a bit to see our triangle in it's glory.
  159.         glTranslatef(0, 0, -5);
  160.        
  161.         // --- VBO's in action.
  162.         // Set the vertexBuffer as the current buffer.
  163.         glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
  164.        
  165.         // Specify that it's data is vertex data.
  166.         glVertexPointer(3, GL_FLOAT, 0, 0);
  167.        
  168.         // Set the colourBuffer as the current buffer.
  169.         glBindBufferARB(GL_ARRAY_BUFFER_ARB, colourBuffer);
  170.        
  171.         // Specify that it's data is colour data.
  172.         glColorPointer (3, GL_FLOAT, 0, 0);
  173.        
  174.         // Tell OpenGL to draw what it sees. ;)
  175.         glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
  176.         // --- End VBO's in action.
  177.        
  178.         // Swap buffers!
  179.         SDL_GL_SwapBuffers();
  180.     }
  181.    
  182.     // Disable the client states.
  183.     glDisableClientState( GL_VERTEX_ARRAY );
  184.     glDisableClientState( GL_COLOR_ARRAY );
  185.    
  186.     //!TODO: Free the buffers created in glBufferDataARB
  187.    
  188.     return 0;
  189. }
Share or Store:
  • Digg
  • del.icio.us

16 Comments »

RSS feed for comments on this post. TrackBack URI

  1. Kramer auto Pingback[...] probado los vertex buffer objects, y este articulo os dara un poco igual. Para el resto, aqui podeis leer una descripcion sencilla de como conseguir un uso mas optimizado a la memoria de la [...]

    Pingback by codepixel - Vertex Buffer Objects — January 14, 2008 #

  2. 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 #

  3. 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 #

  4. Kramer auto Pingback[...] vertex buffer objects tutorialSource: http://www.kickingdragon.com/2006/07/25/opengl-ver…Displaying mentions in this article, for full text please visit source.I’ve been dabbling in [...]

    Pingback by OpenGL vertex buffer objects tutorial (://URLFAN) — June 24, 2008 #

  5. doesn’t fucking work

    Comment by dipshit — August 10, 2008 #

  6. 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 #

  7. 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 #

  8. 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 #

  9. 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 #

  10. Kramer auto Pingback[...] assuming you mean using display lists (I’m using OpenGL)…? I’m getting there…. Or use Vertex Buffer Objects. I think most video drivers translate display lists into VBO’s internally anyways. [...]

    Pingback by Are Virtual Function Calls Still Expensive? | The Coffeehouse | Channel 9 — December 22, 2008 #

  11. Kramer auto Pingback[...] I took a little bit of time and polished up my demo a bit, and I’ve posted it on my site as a demo . I’d be willing to submit it to DevMaster if people want it. [...]

    Pingback by VertexBufferObjects problem. - DevMaster.net Forums — April 8, 2009 #

  12. Kramer auto Pingback[...]       I can translate into C++ if it helps, but it's basically the same as this (which is in C++). I'm also using this tutorialAny [...]

    Pingback by VBOs in OpenGL (using Tao framework, if that matters) — October 31, 2009 #

  13. 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 #

  14. Kramer auto Pingback[...] tut here http://kickingdragon.com/2006/07/25/opengl-vertex-buffer-objects-tutorial/ which shows just [...]

    Pingback by Inside3d Forums :: View topic - Not exactly related to quake but VBO's — December 1, 2010 #

  15. Really simple thank you. Converted to win32 but core is the same and works 100%. Still valid after all this time 8)

    Comment by Gavin Simpson — July 25, 2011 #

  16. Kramer auto Pingback[...] = (PFNGLBUFFERDATAARBPROC)wglGetProcAddress("glBufferDataARB"); Pokombinuj z tym @Edit http://kickingdragon…jects-tutorial/ 0 ipb.global.registerReputation( 'rep_post_1010264', { app: 'forums', type: 'pid', [...]

    Pingback by [OpenGL] Problem z wy¶wietlaniem obiektów za pomoc± VBO - theModders — October 29, 2011 #

Leave a comment