1

I have recently figured out how to render 3D cubes using LWJGL and OpenGL and I was so excited, I rendered 2000 and effectively froze my computer. I've heard of things such as Display Lists and VBO but even after googling, I have no idea how to use them.

Currently, I have

for (Block b : blocks) {
    GL11.glTranslatef(b.position.x, b.position.y, b.position.z); // Translate to draw the cube.
    GL11.glBegin(GL_QUADS); // Start to draw the quad.
    b.render(); // Renders the quad.
    GL11.glEnd(); // Finishes rendering.
}

Rendering my cubes. The call b.render just renders a cube

@Override
public void render() {
    //front face
    GL11.glNormal3f(0f, 0f, 1f);
    GL11.glTexCoord2f(0f, 1f);
    GL11.glVertex3f(1f, 0f, 0f);
    GL11.glTexCoord2f(1f, 1f);
    GL11.glVertex3f(0f, 0f, 0f);
    GL11.glTexCoord2f(1f, 0f);
    GL11.glVertex3f(0f, 1f, 0f);
    GL11.glTexCoord2f(0f, 0f);
    GL11.glVertex3f(1f, 1f, 0f);

    //back face
    GL11.glNormal3f(0f, 0f, -1f);
    GL11.glTexCoord2f(0f, 1f);
    GL11.glVertex3f(0f, 0f, 1f);
    GL11.glTexCoord2f(1f, 1f);
    GL11.glVertex3f(1f, 0f, 1f);
    GL11.glTexCoord2f(1f, 0f);
    GL11.glVertex3f(1f, 1f, 1f);
    GL11.glTexCoord2f(0f, 0f);
    GL11.glVertex3f(0f, 1f, 1f);

    cap.bind(); // top texture
    //top face
    GL11.glNormal3f(0f, -1f, 0f);
    GL11.glTexCoord2f(0f, 1f);
    GL11.glVertex3f(1f, 1f, 0f);
    GL11.glTexCoord2f(1f, 1f);
    GL11.glVertex3f(0f, 1f, 0f);
    GL11.glTexCoord2f(1f, 0f);
    GL11.glVertex3f(0f, 1f, 1f);
    GL11.glTexCoord2f(0f, 0f);
    GL11.glVertex3f(1f, 1f, 1f);

    //bottom face
    GL11.glNormal3f(0f, 1f, 0f);
    GL11.glTexCoord2f(0f, 1f);
    GL11.glVertex3f(1f, 0f, 1f);
    GL11.glTexCoord2f(1f, 1f);
    GL11.glVertex3f(0f, 0f, 1f);
    GL11.glTexCoord2f(1f, 0f);
    GL11.glVertex3f(0f, 0f, 0f);
    GL11.glTexCoord2f(0f, 0f);
    GL11.glVertex3f(1f, 0f, 0f);

    side.bind(); // left texture
    //left face
    GL11.glNormal3f(-1f, 0f, 0f);
    GL11.glTexCoord2f(0f, 1f);
    GL11.glVertex3f(1f, 0f, 1f);
    GL11.glTexCoord2f(1f, 1f);
    GL11.glVertex3f(1f, 0f, 0f);
    GL11.glTexCoord2f(1f, 0f);
    GL11.glVertex3f(1f, 1f, 0f);
    GL11.glTexCoord2f(0f, 0f);
    GL11.glVertex3f(1f, 1f, 1f);

    //right face
    GL11.glNormal3f(1f, 0f, 0f);
    GL11.glTexCoord2f(0f, 1f);
    GL11.glVertex3f(0f, 0f, 0f);
    GL11.glTexCoord2f(1f, 1f);
    GL11.glVertex3f(0f, 0f, 1f);
    GL11.glTexCoord2f(1f, 0f);
    GL11.glVertex3f(0f, 1f, 1f);
    GL11.glTexCoord2f(0f, 0f);
    GL11.glVertex3f(0f, 1f, 0f);
}

Where cap is the top Texture and side is the side Texture.

What I really need help with is figuring out how to make my code VBO and/or Display List compatible in order to increase performance. I also think if it were possible to render only visible faces it would save many computations but can't think of how to do such a thing.

EDIT:

I now have each block creating its own VBO object via the following code...

private int vboID;
private FloatBuffer vertices;
private float[] verts = {0, 1, 2, 2, 3, 0, 0, 3, 4, 4, 5, 0, 0, 5, 6, 6, 1, 0, 1, 6, 7, 7, 2, 1, 7, 4, 3, 3, 2, 7, 4, 7, 6, 6, 5, 4}; // Not sure on the numbers for making a cube?

private void generateVBO() {
    vertices = BufferUtils.createFloatBuffer(verts.length); // Create a FloatBuffer...
    vertices.put(verts); // Add all the vertices in...
    vboID = GL15.glGenBuffers(); // Generate the VBO...
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID); // Bind it...
    GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertices, GL15.GL_STATIC_DRAW); // Buffer in the data...
    verts = null; // Free up memory allocation because these are unnecessary now...
    vertices = null;
    System.out.println("VBO created with a vboID of '"+vboID+"'.");
}

At the start of my program, I create 1000 block objects so my output is effectively "VBO create with a vboID of n", 1000 times.

I understand at the end of the program, I need to dispose of the VBOs (I'm presuming I just call GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0) for each VBO?) but first, I need to draw each VBO.

What is the command to draw VBOs?

hoijui
  • 3,615
  • 2
  • 33
  • 41
user1887053
  • 13
  • 1
  • 5

2 Answers2

1

Please don't use Display Lists, they're outdated and deprecated. Using VBOs effectively requires using Vertex Arrays. When using a vertex array you put all the vertex positions and other attributes into arrays and then batch the drawing of a lot of triangles using a single call to glDrawArrays (assumes the arrays are just a long list of vertices to be processed one after another) or glDrawElements (takes an additional array, that contains a list of indices referring to the elements in the vertex arrays).

Here's a tutorial about vertex arrays:

http://www.songho.ca/opengl/gl_vertexarray.html

Once you got vertex arrays working, its only a small step to VBOs.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • Excellent information. I've done all that now, I just need to figure out how to draw my VBO object in my render loop. Here's what I have so far to create my VBO: (see edit) – user1887053 Feb 12 '13 at 19:14
  • @user1887053: You should not create a separate VBO for each block. Put them all into one single VBO. Otherwise you're still creating a lot of call overhead. Also you dispose of the VBOs with glDeleteBuffer, glBindBuffer(…, 0) just unbinds it and you can later rebind it. – datenwolf Feb 12 '13 at 19:42
  • Eventually, there will be upwards of 50 different textures for blocks so I assume I need at least one VBO for each block type... Something like creating a single VBO and adding blocks to it whenever necessary I suppose... That will help performance but I still need to know how to actually draw each component of the VBO. Additionally, and this might be answered with the VBO draw method but how would I have individual block coordinates if there were multiple blocks contained within a single VBO? Thanks for your help, as I'm sure you realize, I'm a complete beginner to OpenGL – user1887053 Feb 12 '13 at 19:56
  • VBOs don't equal to models! VBOs are just memory you reference. Just make a separate glDraw… call per used texture. The batch drawn will of course only include the triangles using that texture. – datenwolf Feb 12 '13 at 20:04
  • Ah, that makes more sense. So to be sure, I only need one single VBO that is created during initialization. For every block added to the VBO, I give it... The coordinates of each vertex? And finally, in my render loop, I... Loop through each block and use the VBO to help draw the cube model? I think I'm starting to understand but I obviously need to do more reading. – user1887053 Feb 12 '13 at 20:14
0

display list only store opengl primitive which means it only store glVertex/glTexCoord etc. And does not store any client functions like glEnableClientState/glDisableClientSate/glDrawArrays etc.

To setup display list here are the example code:

int var = glGenLists(1);

glNewList(var, GL_COMPILE);
// put your vertex/primitives here
glEndList();

glCallList(var) // execute/draw them

TIP: Don't put the glNewList/glEndList in a loop it will cause performance drop, only glCallList

Fun Fact: Display List can improve performance by about 5-10%.

However Display Lists is now deprecated/removed in earlier version of opengl so don't use that in modern OpenGL instead use VBO.