无限立方体世界引擎(如Minecraft)优化建议?

时间:2014-01-09 10:47:15

标签: opengl optimization minecraft cube voxel

Voxel引擎(如Minecraft)优化建议?

作为一个有趣的项目(让我的Minecraft-adict儿子为编程兴奋)我正在使用C#.NET4.5.1,OpenGL和GLSL 4.x构建一个类似3D Minecraft的体素引擎。

现在我的世界是用块建造的。块存储在字典中,我可以根据64位X | Z<<32键选择它们。这允许创建一个可以缓存和缓存块的“无限”世界。

  • 每个块由16x16x16块段组成。从0级基岩开始,它可以达到你想要的高度(不像我认为限制为256的我的世界)。

  • 当Chunks进入视图并需要渲染时,它们会在一个单独的线程上排队生成。这意味着块可能不会立即显示。在实践中你不会注意到这一点。注意:我不是在等待它们生成,它们不会立即显示。

  • 当第一次需要渲染块时,会生成该块的VBO(glGenBufferGL_STREAM_DRAW等),其中包含可能的可见/外部面(相邻块)也检查)。 [这意味着在修改邻居时可能需要重新分配一个块]。首次测试时,会为每个线段和透明线段测试不透明面。每个段都知道它在顶点数组中的起始位置以及它有多少个顶点,包括不透明面和透明面。

  • 纹理取自数组纹理。

渲染时;

  • 我首先使用视锥体的边界框并将其映射到块网格上。利用这些知识,我会选择平截头体内和相机一定距离内的每个块。
  • 现在我对大块进行距离排序。
  • 之后,我确定实际可见的块区段的范围(索引,长度)。现在我确切地知道哪些段(以及哪些顶点范围)在视图中“至少部分地”。我所拥有的唯一多余部分是隐藏在山脉之后或“有时”深埋地下的部分。
  • 然后我开始渲染...首先我使用已知的顶点范围从前到后渲染不透明的面[启用剔除和深度测试,alpha测试和混合禁用]。然后我将透明面渲染回前面[已启用混合]

现在......有没有人知道一种改进方法,仍然允许动态生成无限世界?我目前在平均2.2Ghz i7笔记本电脑上达到 ~80fps @ 1920x1080 ~120fps @ 1024x768 (屏幕截图:http://i.stack.imgur.com/t4k30.jpghttp://i.stack.imgur.com/prV8X.jpg) ATI HD8600M gfx卡。我认为必须增加帧数。而且我想我必须,因为我想添加实体AI,声音并做凹凸和镜面映射。使用Occlusion Queries可以帮助我吗? ......根据细分的性质,我无法想象。我已经最小化了对象的创建,因此整个地方都没有“新对象”。此外,由于在使用调试或发布模式时性能没有真正改变,我认为这不是代码,而是更多解决问题的方法。

编辑:我一直在考虑使用GL_SAMPLE_ALPHA_TO_COVERAGE,但它似乎没有用?

gl.Enable(GL.DEPTH_TEST);
gl.Enable(GL.BLEND); // gl.Disable(GL.BLEND);
gl.Enable(GL.MULTI_SAMPLE);
gl.Enable(GL.SAMPLE_ALPHA_TO_COVERAGE);

3 个答案:

答案 0 :(得分:4)

为了渲染很多类似的对象,我强烈建议你看一下实例化的绘图:glDrawArraysInstanced和/或glDrawElementsInstanced

这给我带来了巨大的变化。我说的是从2 fps到超过60 fps,以渲染100000个类似的二十面体。

您可以使用Attribs(glVertexAttribDivisor和朋友)对多维数据集进行参数化,以使它们不同。希望这会有所帮助。

答案 1 :(得分:1)

目前在200fps左右,应该没问题。我做过的三件主要事情是:

1)在单独的线程上生成两个块。 2)在单独的线程上细分块。 3)使用延迟渲染管道。

不要认为最后一个对整体性能做出了很大贡献,但由于某些着色器而不得不开始使用它。现在CPU有点睡着了~~ 11%。

答案 2 :(得分:1)

这个问题很老了,但我正在开展一个类似的项目。我几乎和你一样接近它,但是我在一个额外的优化中添加了很多帮助。

对于每个块,我确定哪些边是完全不透明的。然后我使用这些信息通过块来填充洪水来剔除地下的洪水。注意,我在进行泛洪填充时没有检查单个块,只有每个块的预先计算的位掩码。

当我计算位掩码时,我还检查块是否完全为空,因为显然可以忽略空块。