我想使用OpenGl(lwjgl)制作Minecraft块渲染。
无论如何我做到了但是我遇到了FPS问题。我希望有人可以告诉我如何优化它,这样我可以更快地渲染更多的块。我将向您展示代码,该代码显示我到目前为止基于0和1值渲染简单地图。
CODE:
块计算:
public void calculate(){
for(int x=0;x<w;x++)
for(int y=0;y<d;y++)
for(int z=0;z<h;z++){
for(int i=0;i<6;i++){
Vector3 d =dir[i];
if(isVisible(x,y,z)==false)continue;
if(!isVisible(-(int)d.x+x,-(int)d.y+y,-(int)d.z+z) ){
pList.add(new Point4B((byte)x,(byte)y,(byte)z,(byte) i));
}
}
}
这就是我根据3D位数进行计算的方式: Point4B只有参数位置x,y,z和side s 多数民众赞成我如何渲染大块:
public void draw(){
for(Point4B a : pList){
glPushMatrix();
glTranslatef(a.x,a.y,a.z);
glBegin(GL_QUADS);
DrawSide((int)a.s);
glEnd();
glPopMatrix();
}
pList是我需要渲染的所有rects的列表 这是我渲染所有块的代码:
for(float x=0;x<16;x++){
for(float z=0;z<16;z++){
glPushMatrix();
glTranslatef((float)x*16,0f,(float)z*16);
chunks[(int)x][(int)z].draw();
glPopMatrix();
}
这里我渲染16x16块,这非常慢。
我知道我可以做一些优化来渲染块之间的边缘但是我相信即使这样我仍然无法渲染大约50个没有巨大FPS伤害的块
我在这里画边:
switch(side){
case B_UP:
glColor3f(0.1333f,0.54509f,0.1333f);
glVertex3f(-1,1,-1);
glVertex3f(1,1,-1);
glVertex3f(1,1,1);
glVertex3f(-1,1,1);
break;
对于6方的所有案例等等
请注意我是否错过了解释的内容
答案 0 :(得分:1)
你应该使用背面剔除,并且有一些算法将块的边与最大的可用面相结合。你不应该使用立即模式而不是现代的opengl。 尝试搜索有用的体素引擎教程。
答案 1 :(得分:0)
您的代码非常有条理,问题在于简单的可伸缩性,正如Csoki所说,除了小型原型之外,您应该避免使用立即模式。
立即模式是创建太多矩阵,因为你可以看到你正在为每个块推送和弹出一个新矩阵以及每个面部的样子? (DrawSide
在你的第二个代码体中)。我确信你可以在真实的游戏引擎中想象每个对象只更改一次矩阵,这是通过假设顶点是该对象位置的本地(在你的情况下是块)来完成的,所以我建议你改变这段代码
glPushMatrix();
glTranslatef(block.X, block.Y, block.z);
glVertex3f(-1,1,-1);
glVertex3f(1,1,-1);
glVertex3f(1,1,1);
glVertex3f(-1,1,1);
glPopMatrix();
简单地
glVertex3f(-1+block.X, 1+block.Y, -1+block.Z);
glVertex3f(1+block.X, 1+block.Y, -1+block.Z);
glVertex3f(1+block.X, 1+block.Y, 1+block.Z);
glVertex3f(-1+block.X, 1+block.Y, 1+block.Z);
这样您就不必为每个块或面创建一个新矩阵,只需要在块中为每个面部留下一个巨大的GL_QUADS列表,这对于更高级的功能更为简单,我强烈建议您使用例如显示列表和顶点缓冲对象(VBO)。这些允许模型存储在GPU中或至少更接近它,同时减少代码的负担。