2011-02-14 60 views
6

我正在写一个类似于C++/openGL的静态3d块世界的Minecraft。我正在改善帧速率,到目前为止我已经使用八叉树实现了平截体。这有帮助,但我仍然看到中等到不好的帧速率。下一步将是通过更紧密的立方体来剔除隐藏在视点中的立方体。然而,我还没有找到很多关于如何实现这一目标的资源。3d闭塞剔除

+0

您已经阅读过关于z-buffers的内容吗? http://de.wikipedia.org/wiki/Z-Buffer – 2011-02-14 18:11:59

+2

@Thomas:你可能的意思是http://en.wikipedia.org/wiki/Z-Buffer :) – 2011-02-14 18:13:02

+0

我已经简要地阅读了他们,但还不够知道如何使用它们。我将不得不阅读更多内容。 – 2011-02-14 18:13:10

回答

7

使用Z缓冲区(或“深度缓冲区”)创建渲染目标。然后确保对所有不透明物体进行排序,以便它们从前到后进行渲染,即先排列最接近相机的物体。任何使用阿尔法混合的东西仍然需要重新渲染,在渲染完所有不透明物体之后。

另一种技术是遮挡剔除:您可以便宜地“干燥”呈现您的几何图形,然后找出有多少像素在深度测试中失败。在DirectX和OpenGL中有遮挡查询支持,但并非每个GPU都能做到。

缺点是您需要渲染和获取结果之间的延迟 - 取决于设置(如使用预测平铺时),它可能是全帧。这意味着你需要在那里创意,比如渲染一个比对象本身更大的边界框,并在相机切割后解除结果。

还有一件事:更传统的解决方案(您可以与遮挡剔除同时使用)是一个房间/门户系统,您可以将区域定义为“房间”,通过“门户”连接。如果从当前房间看不到门户,则无法看到与其连接的房间。即使是这样,您可以点击您的视口,查看通过门户可见的内容。

3

如果您的表面靠近相机,您可以创建一个表示不可见区域的平截头体,并剔除完全包含在该平截体中的对象。在下图中,C是相机,|是相机附近的平坦表面,由.组成的截锥形区域代表遮挡区域。表面被称为antiportal

 . 
     .. 
     ... 
    .... 
    |.... 
    |.... 
    |.... 
    |.... 
C |.... 
    |.... 
    |.... 
    |.... 
    .... 
     ... 
     .. 
     . 

(你当然应该也开启深度测试和深度写在对方的回答和评论提及的 - 这是非常简单的在OpenGL做的。)

4

多少块,你渲染和什么硬件?现代硬件速度非常快,几何难度很大(除非我们正在谈论手持平台)。在任何适度的近期桌面硬件上,您应该能够以每秒60帧的速度渲染每帧数十万个立方体,而不需要任何花哨的剔除技巧。

如果你使用单独的绘图调用(glDrawElements/Arrays,glBegin/glEnd等)绘制每个块(奖励点:不使用glBegin/glEnd),那么这将是你的瓶颈。这是初学者常见的陷阱。如果你正在这样做,那么你需要将所有共享纹理和阴影参数的三角形集中在一起,为每个设置调用一次。如果几何图形是静态的,并且不会逐帧更改,则需要为每批三角形使用一个Vertex Buffer Object

如果您一次只能在视锥体中只有一小部分游戏世界,那么仍然可以将其与截锥体与八叉树组合使用。顶点缓冲区仍然是静态加载的,没有改变。 Frustum剔除八叉树,仅为平截头体中的三角形生成索引缓冲区,并在每帧中动态上传这些缓冲区。

5

我在this minecraft level renderer中采取的方法本质上是一个平截头体有限的填充。16x16x128块被分割成16x16x16块,每个块都带有一个具有相关几何图形的VBO。我开始在玩家位置的数据块网格中进行填充,以查找要呈现的数据块。填充是通过限于:

  1. 的视锥体
  2. 固体chunklets - 如果至数据块的整个侧面是不透明的块,然后此时,floodFill不会在该方向输入至数据块
  3. 方向 - 洪水将不会反转方向,例如:如果当前小块位于起始小块的北部,则不要向小块南部溢出

它似乎可以正常工作。我在android上,所以虽然更复杂的分析(如Mike Daniels所指出的反向门户)会挑选更多的几何体,但我已经受到CPU限制,所以没有多少意义。

我刚刚看到了你对Alan的回答:剔除不是你的问题 - 这是什么以及你如何发送到OpenGL很慢。

绘制内容:不要渲染每个块的立方体,渲染边框不透明块的透明块的面。考虑一个3x3x3的立方体,比如说石块:没有必要画出中心块,因为玩家无法看到它。同样,玩家永远不会看到两个相邻的石块之间的面孔,所以不要画它们。

如何绘制:如Alan所述,使用VBOs批量几何。你不会相信他们做得多快。

一个更简单的方法,只需对现有代码进行最小的更改即可使用display lists。这是我的世界使用的。

-2

使用Z缓冲确保多边形正确重叠。

启用深度测试后,每个绘图操作都会在将像素放置在屏幕上之前检查Z缓冲区。

如果你有凸对象,你必须(为了性能)启用背面剔除!

示例代码:

glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE);

您可以更改glCullFace的行为()传递GL_FRONT或GL_BACK ...

glCullFace(...);

//绘制的 “游戏世界”。 ..