当前位置: 首页 > 知识库问答 >
问题:

如何停止渲染不可见面

方砚
2023-03-14

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

重点是,我需要生成很多立方体。每次我渲染超过16x16x16块的theese块时,我的FPS几乎都会下降,因为它渲染了所有theese立方体的所有6个面。那是24576个四边形,我不想要。

所以,我的问题是,如何停止渲染不可见的顶点(或四边形),从而提高我的游戏性能?

以下是用于渲染块的类:

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个答案

端木淇
2023-03-14

一个好主意是不要使用即时模式来渲染块,我使用显示列表,因为它们最容易设置,而且速度非常快。其次,即使你仍然只使用即时模式,然后在你画图时只使用一个glBegin/glEnd调用,在将来使用纹理图集进行纹理,对于你的主要问题是如何停止渲染不可见的面,这是非常简单的,我这样做的方式基本上是为每个面创建六个方法,返回一个布尔值。如果面方向上的块类型是空气块(如果是),则返回简单的结果。那么这意味着它将返回true,因此将其渲染。在绘制方法中,添加参数“布尔背面、布尔顶面……等”和一个if语句,检查要绘制哪一侧。

希望我能帮忙,祝你好运!

孔琪
2023-03-14

正如ulmangt所说,我建议您使用VBO,但在此之前,您只需要计算可见面。

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

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

所以用一个由体素构成的5x5x5立方体,而不是750个四边形,你最终得到了150个。

其他收益可以通过在视图中渲染组块(一组体素)(忽略玩家后面的组块)和使用距离限制来获得。

如果使用八叉树只渲染您知道可能可见的块,您可能会变得更加疯狂。

蒋岳
2023-03-14

您的代码有一个更大的性能问题。您不应该使用立即模式OpenGL渲染(glVertex XXX()调用)来绘制如此大量的顶点。

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

相反,应该使用顶点缓冲区对象。这将允许您将所有几何体直接上传到图形卡上,然后在单个Java方法调用中绘制所有立方体(可能是glDrawArrays)。

 类似资料:
  • < b >想改进这个问题?通过编辑此帖子添加详细信息并澄清问题。 我用lwjgl框架做了一个游戏——它使用opengl窗口来渲染。我想每5秒钟渲染一次,而不停止游戏的更新。有什么方法可以做到这一点,直接用lwjgl还是用opengl?我猜这应该不是非常复杂,但我似乎找不到任何东西。

  • 问题内容: 每次在React.js中执行渲染时,UI都会滚动到页面顶部。 JSFiddle:http : //jsfiddle.net/bengrunfeld/dcfy5xrd/ 有什么漂亮或 反应性的 方式可以阻止这种情况吗? 例如,如果用户向下滚动页面,然后按下导致渲染的按钮,则UI将保持与以前相同的滚动位置。 更新:为什么UI滚动到某些渲染的顶部,而不滚动到其他渲染? 问题答案: @floy

  • 它还在继续被渲染。我想阻止它。 由于这个问题,从Api接收到的照片和文本一直在随机变化。 我认为使用效果是问题所在。请让我知道,因为我是初学者。 这是useFetch.jsx 这是Main.jsx

  • 我为我的草图创建了一个简单的延迟函数,并试图使用它,但似乎渲染停止了,也就是说,有一个简单的灰色屏幕,然后一切都被一次渲染。 有人能告诉我我在哪里吗出错了?到底发生了什么? 如何在内部定义绘制()和设置()?我知道,set()是一个一次性的渲染和绘制(),就像一个无限的循环。 代码:

  • 问题内容: 我目前正在使用 Swift 测试将AVPlayer与音频流URL一起使用。有play()和pause()方法,但是问题在于,仅暂停,流仍会缓存在设备中。 这是我的测试代码: 这是尝试某些东西时的问题: :“无法将’NilLiteralCOnvertible’类型的值分配给’AVPlayer’类型的值” :“无法分配给属性:’currentItem’是仅获取属性” 我尝试了所有操作,即使

  • 问题内容: 在我的Maven项目中,我创建了一个“ index.xhtml”文件。当我构建并运行该项目时,Web浏览器未显示任何内容。当我查看源代码时,仍然可以看到源代码,而不是普通的html标签。 我尝试通过以下方式创建XHTML文件: 选择项目,右键单击New ..并选择Other ..并选择“ Web”类别,然后选择JSF Page。 选择项目,右键单击New ..,然后选择Other ..