VBOs my worst nightmare

No matter how many tutorials or YouTube videos I follow, I could never understand VBOs the same. one article or video tells me one thing, another tells me something different. I’m not leaving this post without a way better understanding of VBOs. So, apparently VAOs are a list of VBOs which are lists of points in space. They are saved so the GPU can acess them faster than immediate mode I believe. Here is code from a well known video that I added comments about what I think each block of code did. Instead of asking each after each, I thought you guys could just correct me on anything I don’t understand well. Each block where I added a capitalized comment; I’d appreciate it if you would just explain the code under it(or I could just ask if nobody mentions it :P) .

public class VertexBufferObjectDemo {

    public static void main(String[] args) {
    	//CREATS DISPLAY
    	
        try {
            Display.setDisplayMode(new DisplayMode(640, 480));
            Display.setTitle("Vertex Buffer Object Demo");
            Display.create();
        } catch (LWJGLException e) {
            e.printStackTrace();
            Display.destroy();
            System.exit(1);
        }
        
        
        
        //ENABLES DISPLAY WITH A ORTHO THAT IS VERY SMALL
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(1, -1, 1, -1, 1, -1);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        //VERTICIES AND STUFF
        final int amountOfVertices = 3;
        final int vertexSize = 3;
        final int colorSize = 3;
        
        //VARIABLE I USE
        float trans = 0.1f;
        
        
        //CREATES THE POINTS FOR THE TRIANGLE
        FloatBuffer vertexData = BufferUtils.createFloatBuffer(amountOfVertices * vertexSize);
        vertexData.put(new float[]{-0.5f + trans, -0.5f, 0, 0.5f + trans, -0.5f, 0, 0.5f + trans, 0.5f, 0});
        vertexData.flip();

        FloatBuffer colorData = BufferUtils.createFloatBuffer(amountOfVertices * colorSize);
        colorData.put(new float[]{1, 0, 0, 0, 1, 0, 0, 0, 1});
        colorData.flip();
        
        //SETS UP VERTEX STUFF
        int vboVertexHandle = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
        glBufferData(GL_ARRAY_BUFFER, vertexData, GL_DYNAMIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        
        //SETS UP COLOR STUFF
        int vboColorHandle = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboColorHandle);
        glBufferData(GL_ARRAY_BUFFER, colorData, GL_DYNAMIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        while (!Display.isCloseRequested()) {
            glClear(GL_COLOR_BUFFER_BIT);
            
          // Clear the vertices buffer
            vertexData.clear();

           
            // Re-create the vertex data (personal use)
            vertexData.put(new float[]{-0.5f + trans, -0.5f, 0, 0.5f + trans, -0.5f, 0, 0.5f + trans, 0.5f, 0});
            vertexData.flip();
            
            

            // Now, upload to the GPU (personal use)
            glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
            glBufferData(GL_ARRAY_BUFFER, vertexData, GL_DYNAMIC_DRAW);

            
            
            //PREPARES TO DRAW CRAP
            glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
            glVertexPointer(vertexSize, GL_FLOAT, 0, 0L);

            glBindBuffer(GL_ARRAY_BUFFER, vboColorHandle);
            glColorPointer(colorSize, GL_FLOAT, 0, 0L);
            
            
            

            glEnableClientState(GL_VERTEX_ARRAY);
            glEnableClientState(GL_COLOR_ARRAY); 
            //DRAWS TRIANGLE USING THE FLOAT POINTS
            glDrawArrays(GL_TRIANGLES, 0, amountOfVertices);
            glDisableClientState(GL_COLOR_ARRAY);
            glDisableClientState(GL_VERTEX_ARRAY);

            Display.update();
            Display.sync(60);
        }

        glDeleteBuffers(vboVertexHandle);
        glDeleteBuffers(vboColorHandle);

        Display.destroy();
        System.exit(0);
    }
}

Your comments aren’t very descriptive so it’s hard to discern your level of understanding, but it looks like you’re on the right track.

I’ll take a crack at the following for you though:


//Here you are having openGL get an index for you. This is (should be) a valid
//unused index in the buffer array.
int vboVertexHandle = glGenBuffers();
//Here you are telling openGL that you are about to use
//the buffer - buffer[vboVertexHandle]
glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
//Now at buffer[vboVertexHandle] you are putting the data you created into it.
glBufferData(GL_ARRAY_BUFFER, vertexData, GL_DYNAMIC_DRAW);
//This resets the buffer to a non used buffer so you don't have any accidents
glBindBuffer(GL_ARRAY_BUFFER, 0);

The color buffer is the same idea.


// Since you are able to change which buffer you are playing with everytime you 
//draw an object to want to make sure that you are using the correct buffer
//So you rebind the buffer
glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
//Here you are telling openGL that the currently binded buffer defines vertex
//positions, the size of the positional values, their type, and how they are
//stored(interleaved - but don't worry about that right now)
glVertexPointer(vertexSize, GL_FLOAT, 0, 0L);

Again the same idea for color.

Am I correct that VBOs are created and saved in the GPU, then used whenever it is rendered?

[quote] //PREPARES TO DRAW CRAP
glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
glVertexPointer(vertexSize, GL_FLOAT, 0, 0L);

        glBindBuffer(GL_ARRAY_BUFFER, vboColorHandle);
        glColorPointer(colorSize, GL_FLOAT, 0, 0L);

[/quote]
Based off of what you said I’m storing the index data here in the render loop (If I’m correct) .

 glEnableClientState(GL_VERTEX_ARRAY);
            glEnableClientState(GL_COLOR_ARRAY); 
            //DRAWS TRIANGLE USING THE FLOAT POINTS
            glDrawArrays(GL_TRIANGLES, 0, amountOfVertices);
            glDisableClientState(GL_COLOR_ARRAY);
            glDisableClientState(GL_VERTEX_ARRAY);

So if I had a triangle or any other shape with different verticies, I would just do this?

glDrawArrays(GL_TRIANGLES, 0, amountOfVertices2);

Also, besides clarifying myself, I got lost when videos would talk about an ID? What’s this ID as well as a VBO stored in a VAO?

Yes

It will use whatever VBO is currently bound.

Essentially, yes. Just however many vertices you want to draw with the currently bound buffer. I like to keep something like an ArrayList (or an array if you already know all the vertices) that stores the vertex data. Then, I can just call [icode]vertices.size() / vertexSize[/icode] (because there are 3 values per vertex) to get the number of vertices.

You already have an array that you is being uploaded, so just make an object that you can reference ([icode]float[] vertices[/icode]) and use that to get the number of vertices.

An ID is how you access the buffers. Opengl gives you a pointer to the buffer, instead of the actual object. You use this ID to access the buffer.

Basically from my understanding, which is not the best, storing a VBO in a VAO is a way to increase performance, less calls made to openGL during rendering (3 instead of ~12). The only problem I can see is that if you’re making changes to the geometry often(once every six frames or less) then you have a lot more load calls to make. These threads contain some info on that and I’m there are people here who’ll know more:

http://www.gamedev.net/topic/644897-when-to-add-a-vbo-to-a-vao/
http://www.opentk.com/node/1619

see http://www.opengl.org/wiki/Vertex_Specification#Vertex_Array_Object

it’s useful when you use alot vertexAttribs. helps keeping them organised.

short story : a vao is a very simple object just storing a few states. using it is just a short-cut to set these states, bit like a display-list. from the spec. :

Additions to Chapter 6 of the OpenGL 2.1 Specification (Querying GL State)

[quote]Queries for VERTEX_ARRAY_POINTER, NORMAL_ARRAY_POINTER,
COLOR_ARRAY_POINTER, SECONDARY_COLOR_ARRAY_POINTER, INDEX_ARRAY_POINTER,
TEXTURE_COORD_ARRAY_POINTER, FOG_COORD_ARRAY_POINTER, or
EDGE_FLAG_ARRAY_POINTER
return the value stored in the currently bound
vertex array object.
[/quote]
guess there are more states with apple and ibm extensions.

in your example instead of

            //PREPARES TO DRAW CRAP
            glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
            glVertexPointer(vertexSize, GL_FLOAT, 0, 0L);

            glBindBuffer(GL_ARRAY_BUFFER, vboColorHandle);
            glColorPointer(colorSize, GL_FLOAT, 0, 0L);
            
            
            

            glEnableClientState(GL_VERTEX_ARRAY);
            glEnableClientState(GL_COLOR_ARRAY); 
            //DRAWS TRIANGLE USING THE FLOAT POINTS
            glDrawArrays(GL_TRIANGLES, 0, amountOfVertices);
            glDisableClientState(GL_COLOR_ARRAY);
            glDisableClientState(GL_VERTEX_ARRAY);

you could do

            //PREPARES TO DRAW CRAP
            GL30.glBindVertexArray(the_vao);
            //DRAWS TRIANGLE USING THE FLOAT POINTS
            glDrawArrays(GL_TRIANGLES, 0, amountOfVertices);
            GL30.glBindVertexArray(0);

i’d say do not use it until you need the performance.