VBO rendering

Ive got some code thats rendering objects to the screen using a vbo, but i feel it’s very inneficient

For example, if i wanted to render a cube i would need (6 faces * 4 vertices) 24 vertices to make one cube when in reality it only has 8

Is there anyway to sort this out?

Use index buffers (GL_ELEMENT_ARRAY_BUFFER) and glDrawElements as well. Example:

Construct ibo.


//gen vbo

int[] indices = new int[] { //This uses quads and depends on the order of the vertices in the vbo but you get the 
    0, 1, 2, 3, //Face 1        picture
    4, 5, 6, 7, //Face 2
    0, 1, 5, 4, //Face 3
    3, 2, 6, 7, //Face 4
    0, 4, 7, 3, //Face 5
    1, 5, 6, 2  //Face 6
};

IntBuffer indicesData = createIntBuffer(indices);

int iboId = glGenBuffer();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboId);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesData, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);


Rendering the quad



bindVBO();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboId);
setupPointers();
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, 0); //Arguments are: render mode, number indices, type of indices
                                                                           //                     and byte offset into indices to start at.


That’s all folks.

But, what if in some cases i didn’t want to render then entire quad? What if i wanted to not render the backface of one cube and maybe not the bottom face of one. I don’t see how using an element array buffer could make that work?

Then you have to leave out the face you don’t want to draw:


int[] indices = new int[] { //This uses quads and depends on the order of the vertices in the vbo but you get the 
    0, 1, 2, 3, //Face 1        picture
    4, 5, 6, 7, //Face 2
//  0, 1, 5, 4, //Face 3 <- leave it out, don't draw it
    3, 2, 6, 7, //Face 4
    0, 4, 7, 3, //Face 5
    1, 5, 6, 2  //Face 6
};

You really need to understand indices. Try some tutorials out there :slight_smile:

But here:

glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, 0);

You’ve told OpenGL to render 24 vertices not 20, so surely this wouldn’t come out right

Ok. So, simply put in 20? Or even better: [icode]indices.length[/icode].

But what if certain quads in that vbo need to have a different number of faces rendered each?

(sorry if im being pickety here, i just like to make sure im not writing horribly inefficient code ;D)

You might be confusing some terminologies here. A quad is a face, actually. Or in other words: A quad has 4 vertices.

So a quad only consists of one face… :persecutioncomplex:

You can if you wish draw each face individually using the offset parameter of glDrawElements:



glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, 0);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, 16); //16 is 4 indices of integers, integers are 4 bytes each.
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, 32); //2 * 16
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, 48); //3 * 16 
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, 64); //4 * 16
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, 80); //5 * 16


There is also a glMultDrawElements method but if you’re using LWJGL, this method is not available (too much messing around with pointers) and presumably that means it is not available to LibGDX as well.

matheus23 : Apologies, i meant to say cube

quew8 : I can see what you’re trying to say here but say i have lots of cubes stored in one vbo, i don’t want to be rendering all the faces individually

WARNING LONG DESCRIPTION AHEAD.

The way I often do it is to store an array of “handles” to objects (so in your case it could be a face,a cube, a group of cubes or whatever, you could also have the ability to access a whole cube or a particular face in that cube etc). Each handle stores the starting offset in the index buffer and the number of indices needed to be be drawn.

Each frame I find the first handle in the array that needs to be drawn, and store its offset. Then I iterate through, adding the number of indices to a counter until I find one that shouldn’t be drawn. Then I call glDrawElements with the stored offset and the counter for number of indices. Then I keep going until the next one that needs to be drawn.

I know this seems like a waste, but IMHO, it is the best way to have complete choice over what is rendered and also minimize OpenGL calls which are generally the slow bits. You can group whole lots of things together (like a whole room or a character mesh) so I find it works quite well with occlusion detection when store things in a tree/scene graph type thing. You can eliminate an entire branch and half the iterations.

As ever computer graphics are an art form, not a science or religion, and there is no one true path. This suits me well but may not you.