如何停止渲染隐形面孔

时间:2012-04-06 15:16:24

标签: java opengl lwjgl voxel

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

重点是,我需要生成大量的立方体。每当我渲染超过16x16x16块的theese块时,我的FPS几乎没有下降,因为它渲染了所有theese立方体的所有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);

      }
    }
  }
}

3 个答案:

答案 0 :(得分:3)

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

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

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

答案 1 :(得分:2)

我建议,就像ulmangt所说,你使用VBO但在此之前,你需要只计算可见的面孔。

这可以通过(仅在开始时)检查面部是否与空体素(“空气”)相邻来轻松完成。如果是,请将四边形(面)添加到渲染中。

之后,您只需对已更改的体素的邻居进行此检查。示例:当用户删除多维数据集时,请检查该体素的6个邻居并将这些四边形添加到渲染中。添加体素时反向执行,删除邻居四边形。

因此,使用由体素制成的5x5x5立方体而不是750个四边形,最终得到150个。

只需在视图中渲染块(一组体素)(忽略播放器背面的块)并使用距离限制即可获得其他增益。

你可以通过使用八叉树来渲染你知道可能可见的块来变得更加疯狂。

答案 2 :(得分:1)

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

希望我帮忙,祝你好运!