I am making a voxel-based game, and for needs of it, i am creating a block rendering engine.
Point is, that i need to generate lots of cubes. Every time i render more than 16x16x16 chunk of theese blocks, my FPS is dropped down hardly, because it renders all 6 faces of all of theese cubes. That’s 24 576 quads, and i dont want that.
So, my question is, How to stop rendering vertices(or quads) that are not visible, and therefore increase performance of my game?
Here is class for rendering of a block:
public void renderBlock(int posx, int posy, int posz) {
try{
//t.bind();
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);// or even GL_FRONT_AND_BACK */);
glPushMatrix();
GL11.glTranslatef((2*posx+0.5f),(2*posy+0.5f),(2*posz+0.5f)); // Move Right 1.5 Units And Into The Screen 6.0
GL11.glRotatef(rquad,1.0f,1.0f,1.0f);
glBegin(GL_QUADS); // Draw A Quad
GL11.glColor3f(0.5f, 0.4f, 0.4f); // Set The Color To Green
GL11.glTexCoord2f(0,0);
GL11.glVertex3f( 1f, 1f,-1f); // Top Right Of The Quad (Top)
GL11.glTexCoord2f(1,0);
GL11.glVertex3f(-1f, 1f,-1f); // Top Left Of The Quad (Top)
GL11.glTexCoord2f(1,1);
GL11.glVertex3f(-1f, 1f, 1f); // Bottom Left Of The Quad (Top)
GL11.glTexCoord2f(0,1);
GL11.glVertex3f( 1f, 1f, 1f); // Bottom Right Of The Quad (Top)
//GL11.glColor3f(1.2f,0.5f,0.9f); // Set The Color To Orange
GL11.glTexCoord2f(0,0);
GL11.glVertex3f( 1f,-1f, 1f); // Top Right Of The Quad (Bottom)
GL11.glTexCoord2f(0,1);
GL11.glVertex3f(-1f,-1f, 1f); // Top Left Of The Quad (Bottom)
GL11.glTexCoord2f(1,1);
GL11.glVertex3f(-1f,-1f,-1f); // Bottom Left Of The Quad (Bottom)
GL11.glTexCoord2f(1,0);
GL11.glVertex3f( 1f,-1f,-1f); // Bottom Right Of The Quad (Bottom)
//GL11.glColor3f(1.0f,0.0f,0.0f); // Set The Color To Red
GL11.glTexCoord2f(0,0);
GL11.glVertex3f( 1f, 1f, 1f); // Top Right Of The Quad (Front)
GL11.glTexCoord2f(1,0);
GL11.glVertex3f(-1f, 1f, 1f); // Top Left Of The Quad (Front)
GL11.glTexCoord2f(1,1);
GL11.glVertex3f(-1f,-1f, 1f); // Bottom Left Of The Quad (Front)
GL11.glTexCoord2f(0,1);
GL11.glVertex3f( 1f,-1f, 1f); // Bottom Right Of The Quad (Front)
//GL11.glColor3f(1f,0.5f,0.0f); // Set The Color To Yellow
GL11.glTexCoord2f(0,0);
GL11.glVertex3f( 1f,-1f,-1f); // Bottom Left Of The Quad (Back)
GL11.glTexCoord2f(1,0);
GL11.glVertex3f(-1f,-1f,-1f); // Bottom Right Of The Quad (Back)
GL11.glTexCoord2f(1,1);
GL11.glVertex3f(-1f, 1f,-1f); // Top Right Of The Quad (Back)
GL11.glTexCoord2f(0,1);
GL11.glVertex3f( 1f, 1f,-1f); // Top Left Of The Quad (Back)
//GL11.glColor3f(0.0f,0.0f,0.3f); // Set The Color To Blue
GL11.glTexCoord2f(0,1);
GL11.glVertex3f(-1f, 1f, 1f); // Top Right Of The Quad (Left)
GL11.glTexCoord2f(1,1);
GL11.glVertex3f(-1f, 1f,-1f); // Top Left Of The Quad (Left)
GL11.glTexCoord2f(1,0);
GL11.glVertex3f(-1f,-1f,-1f); // Bottom Left Of The Quad (Left)
GL11.glTexCoord2f(0,0);
GL11.glVertex3f(-1f,-1f, 1f); // Bottom Right Of The Quad (Left)
//GL11.glColor3f(0.5f,0.0f,0.5f); // Set The Color To Violet
GL11.glTexCoord2f(0,0);
GL11.glVertex3f( 1f, 1f,-1f); // Top Right Of The Quad (Right)
GL11.glTexCoord2f(1,0);
GL11.glVertex3f( 1f, 1f, 1f); // Top Left Of The Quad (Right)
GL11.glTexCoord2f(1,1);
GL11.glVertex3f( 1f,-1f, 1f); // Bottom Left Of The Quad (Right)
GL11.glTexCoord2f(0,1);
GL11.glVertex3f( 1f,-1f,-1f); // Bottom Right Of The Quad (Right)
//rquad+=0.0001f;
glEnd();
glPopMatrix();
}catch(NullPointerException t){t.printStackTrace(); System.out.println("rendering block failed");}
}
Here is code that renders them:
private void render() {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT|GL11.GL_DEPTH_BUFFER_BIT);
for(int y=0; y<32; y++){
for(int x=0; x<16; x++){
for(int z=0; z<16; z++) {
b.renderBlock(x, y, z);
}
}
}
}
I recommend, like ulmangt said, that you use VBO but before that, you need to calculate only the visible faces.
This can be easily done by (just once at the beginning) checking if a face is neighbor to a empty voxel (“air”). If it is, add that quad (face) to the rendering.
Afterwards you just do this check only on the neighbors of changed voxels. Example: When the user removes a cube, check the 6 neighbors of that voxel and add those quads to the rendering. Do the reverse when voxels are added, remove neighbor quads.
So with a 5x5x5 cube made of voxels, instead of 750 quads, you end up with 150.
Other gains can be had by just rendering chunks (a group of voxels) in the view (ignoring the ones to the back of the player) and using a distance limit.
You can go even more crazy by using octrees to only render chunks that you know that could possibly be visible.