我正在制作一个基于体素的游戏,为了满足它的需要,我正在创建一个块渲染引擎。
重点是,我需要生成大量的立方体。每当我渲染超过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);
}
}
}
}
答案 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语句,检查要绘制哪一面。
希望我帮忙,祝你好运!