2012-04-06 99 views
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); 

     } 
    } 
    } 
} 
+0

任何人都可以帮忙吗? – TheMorfeus 2012-04-06 15:49:59

+0

可能的重复[如何去除单位立方体世界中的脸部去除Minecraft?](http://stackoverflow.com/questions/6319655/how-to-do-face-removal-in-a-unit- cube-world-a-la-minecraft) – 2012-04-06 17:25:08

回答

2

与ulmangt一样,我建议您使用VBO,但在此之前,您只需计算可见面。

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

然后,你只是做这个检查只对变化的体素的邻居。例如:当用户移除一个立方体时,检查该体素的6个邻居并将这些四边形添加到渲染中。当体素被添加时做相反的操作,移除相邻的四边形。

有由体素的5×5×立方体

所以,相反的750辆四轮摩托车,你最终与视图150

其他收益可以通过只绘制块可以了(一组体素)(忽略的那些到玩家的后面)并使用距离限制。

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

+0

谢谢:)现在,你有一个如何确定体素是否触及体素的想法? – TheMorfeus 2012-04-12 14:16:11

+0

好吧,块体素只是一个填充了体素类型的3d数组(我认为我的世界使用一个字节来表示indev版本中的体素类型,现在不知道)。想到最简单的方法就是遍历整个数组,并检查每个体素的邻居并将可见四边形添加到列表中。 (TL; DR:遍历体素的三维阵列,忽略“空气”类型的体素,检查邻居的空气体素,添加可见的四边形)。 – 2012-04-13 01:44:14

3

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

以这种方式执行渲染时,代码必须调用每个顶点的图形驱动程序,速度很慢。您可以使用Vertex Buffer Objects。这将允许您将所有的几何图形直接上传到图形卡上,然后用一个Java方法调用(可能是glDrawArrays)绘制所有的多维数据集。

+2

这只是解决了小问题。这里的问题是他试图以暴力的方式进行体素渲染,这没有真正的工作机会。至少不适用于任何重要的输入大小。 – pmr 2012-04-06 16:23:31

+0

我应该如何渲染它? – TheMorfeus 2012-04-07 08:07:41

1

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

希望我帮忙,祝你好运!

+0

这个问题已经超过2年了,我已经使用显示列表解决了问题。尽管如此,我已经远离这个项目。 – TheMorfeus 2014-08-27 12:01:17

+0

我没有阅读日期,但仍然会帮助寻找答案的人。 – ABOODYFJ 2014-08-31 07:34:16