【问题标题】:Speeding up lwjgl rendering?加速 lwjgl 渲染?
【发布时间】:2014-01-17 20:20:09
【问题描述】:

我想使用 OpenGl(lwjgl) 制作 Minecraft 块渲染。

无论如何我都做到了,但我遇到了 FPS 问题。我希望有人能告诉我如何优化它,以便我可以更快地渲染更多块。我将向您展示代码,它显示了到目前为止我是如何基于 0 和 1 值渲染简单地图的。

代码:

块计算:

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 和边 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 是我需要渲染的所有矩形的列表 这是我渲染所有块的代码:

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 面的所有情况以此类推

如果我遗漏了要解释的内容,请注意

【问题讨论】:

  • Use modern OpenGL。 OpenGL 调用越少,你的代码就会越快。即,使用 Vertex Buffer Objects 和 Vertex Array Objects 将所有块一次移动到 GPU 内存中,而不是一次将其添加到一个顶点中。

标签: java opengl render lwjgl minecraft


【解决方案1】:

您应该使用背面剔除,并且有一些算法可以将块的侧面与最大的可用面结合起来。而且你不应该使用即时模式而不是现代的opengl。 尝试搜索它们有用的体素引擎教程。

【讨论】:

  • 我确实使用了背面剔除,但自从我昨天开始使用 opengl 后,我并不真正了解现代 opengl。 Ty 提示:D
  • 如何避免中间模式?
  • 即时模式是glbegin glend类型的东西使用vertexarrayobject和displaylists
【解决方案2】:

您的代码组织得很好,问题在于简单的可扩展性,正如 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 中或至少更靠近它,同时减轻代码的大部分负载。

有关模式信息,请查看我回答的类似问题 here,或我的 MineCraft 实现 here

【讨论】:

  • 中级模式??你的意思是立即模式?
  • @RetoKoradi 正确,我责怪拼写检查。
猜你喜欢
  • 1970-01-01
  • 2012-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多