2

我正在制作一个基于体素的游戏,为了它的需要,我正在创建一个块渲染引擎。

重点是,我需要生成很多立方体。每次我渲染超过 16x16x16 块的这些块时,我的 FPS 几乎不会下降,因为它渲染了所有这些立方体的所有 6 个面。那是 24 576 个四边形,我不想要那个。

所以,我的问题是,如何停止渲染不可见的顶点(或四边形),从而提高我的游戏性能?

这是用于渲染块的类:

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");}
}

这是呈现它们的代码:

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);

      }
    }
  }
}
4

3 回答 3

4

您的代码存在更大的性能问题。您不应该使用即时模式 OpenGL 渲染 ( glVertexXXX() calls) 来绘制如此大量的顶点。

当您以这种方式执行渲染时,您的代码必须为每个顶点调用图形驱动程序,这很慢。

相反,您应该使用Vertex Buffer Objects。这将允许您将所有几何图形直接上传到图形卡上,然后在单个 Java 方法调用中绘制所有立方体(可能glDrawArrays)。

于 2012-04-06T16:22:20.780 回答
2

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.

于 2012-04-09T20:21:00.270 回答
1

一个好主意是不要使用立即模式来渲染你的块,我使用显示列表,因为它们最容易设置并且非常快。其次,即使您仍然只使用即时模式,然后在绘图时只使用一个 glBegin/glEnd 调用,在未来使用纹理图集来处理纹理以及您的主要问题是如何停止渲染不可见的面孔,它很简单,我这样做的方式基本上是为每个返回布尔值的面创建六个方法。如果该面方向的块类型是空气块,您将简单地返回,如果是。那么这意味着它将返回true,因此渲染它。并在您的绘图方法中添加参数“布尔背面,布尔顶面......等”和一个 if 语句检查要绘制哪一面。

希望我有所帮助,祝你好运!

于 2014-08-26T00:37:56.350 回答