Friday, June 8, 2007

Introduction and VBOs

So a quick introduction. My name is Mark and I work for a video game development company as lead graphics engine developer. My posts will usually be about .Net or OpenGL. My posts will not be related to things I do at work, instead they will be about my home projects, which are about video games. So if I speak about something, I will be speaking about my home project implementation, which is never the same as my work implementation :)

So I guess the best place for me to start, is to talk about OpenGL since it's awesome. As a bit of background, my home project is a 3D gaming engine written in C# with interop to OpenGL.

VBOs

When I first started writing in OpenGL, I used things like glBegin() and glVertex3f(). I could never get any decent framefrates. Then I learned about Vertex Arrays which helped a lot, and then I finally learned about VBOs about a year ago. These things are awesome.

So what is a VBO?
A Vertex Buffer Object is a piece of memory on the video card that stores all of your vertices, normals, colors, and texture coordinate data. The fantastic part is that its all saved on the video card so you don't have to do millions of system calls to render your data to the screen.

So how do I make a VBO?
First you need an ID for the VBO:

glGenBuffersARB(1, id);
[glGenBuffersARB(int amountToGenerate, int[] returnValues)]

Now you have ur index, that will be ur pointer to your geometry. Please notice the ARB at the end. OpenGL has the calls with ARB and the ones without!! Both are the same, but the ones with ARB will work on older video cards :)

Now we need to add stuff to it ( like the vertex data). To add to it, we have to bind it first (just like you'd bind a texture)

glBindBufferARB(id[0]);
[glBindBufferARB(int idToBind)]

Now we will put our data in from our program to the video card. In my case data is a float[]

glBufferDataARB(GL_ARRAY_BUFFER, data.length * sizeof(float), data, GL_STATIC_DRAW);
[glBufferDataARB(Type, uint size, void * data, GL_STATIC_DRAW? GL_READ_WRITE?);]

Okay so now you've moved your vertices over to the video card!! And you've got an id that points to that memory ( id[0]). Now we'll want to draw it back to the screen later...

To draw the verts back we'll need to enable the client state for vertices.

glEnableClientState( GL_VERTEX_ARRAY);
glBindBuffer(id[0]);
glVertexPointer(3, GL_FLOAT, 0, 0);
[glVertexPointer(int howManyFloatsInAVertex, int dataTypeOfData, ignore, ignore)]

So since u pass 0 as the address for the pointer, it knows to look for a VBO with the ID in the glBindBuffer call. Which I have set to be id[0]. Now its important to note this is where the different kinds of client states change. If you were configuring the texture UV's you'd have a VBO for those ( or if you wanna be extra fast you'd interleave them all into 1 and use an offset where i have a 0 in the pointer) So lets pretend I made a uv pointer also... I do the lines above and then also add:

glEnableClientState( GL_TEXTURE__COORD_ARRAY);
glBindBuffer(textureVBOid[0]);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
[glTexCoordPointer(int howManyFloatsInAVertex, int dataTypeOfData, ignore, ignore)]

Now i'd have my Vertices ( sized a list of floats where every 3 floats are a vertex, and a list of floats where every 2 are a float for the uv's) All bound and ready to render... 1 line more and we have everything on screen:


glDrawElements( GL_TRIANGLES , totalNumberOfIndices, GL_Unsigned_Int, indices );
[glDrawElements(int drawMode, int amountOfIndicesToDraw, Index data type, void * indexArray)]

If you don't care to render using indices, just make an array of uints called indices and fill it with 1, 2, 3, 4, 5, 6... numVerts. That will just render your vertices in order. Indices can also be put as a VBO as well ;)

So I hope that helps the concept with a little behind the scenes. I'll probably explain how I'm doing fonts in the next one!

Time for work! Take care now.

No comments: