6

我正在用 C++ 和 OpenGL (à la Minecraft) 制作体素引擎,但在我的 3GHz 上使用 ATI X1600 无法获得不错的 fps……我完全没有想法。

当我在屏幕上有大约 12000 个立方体时,它会降到 20fps 以下 - 可悲。

到目前为止,我所做的优化是:截锥体剔除、背面剔除(通过 OpenGL 的 glEnable(GL_CULL_FACE)),引擎仅绘制可见面(当然剔除的面除外)并且它们位于八叉树中。

我试过 VBO,我不喜欢它们,它们并没有显着提高 fps。

Minecraft 的引擎怎么能这么快……我在 10000 个立方体上挣扎,而 Minecraft 可以轻松地以更高的 fps 绘制更多内容。

有任何想法吗?

4

5 回答 5

6

@genpfault:我分析连通性并为外部可见表面生成面。VBO 有一个我 glTranslate()d 的立方体

我不是 OpenGL 方面的专家,但据我了解,这将节省很少的时间,因为您仍然必须将每个立方体发送到卡上。

相反,您应该为所有外部可见表面生成面,将其放入 VBO,然后将其发送到卡并继续渲染该 VBO,直到几何形状发生变化。这为您节省了大量时间,您的卡实际上是在等待处理器向其发送几何信息。

于 2010-12-30T21:37:42.393 回答
4

您应该分析您的代码,以确定应用程序中的瓶颈是在 CPU 还是 GPU 上。例如,您的剔除/八叉树算法可能很慢,在这种情况下,它根本不是 OpenGL 问题。

我还会计算您在每一帧上绘制的立方体数量并将其显示在屏幕上。只是为了让您知道您的剔除程序按预期工作。

最后你没有提到你的立方体是否有纹理。尝试使用较小的纹理或禁用纹理,看看帧率增加了多少。

gDEBugger是一个很棒的工具,可以帮助您找到 OpenGL 的瓶颈。

于 2010-12-30T15:24:24.467 回答
2

我不知道在这里“碰到”一个老问题是否可以,但我想到了一些事情:

如果您的体素是静态的,您可以通过使用八叉树进行平截头体剔除等来加快整个渲染过程。此外,您还可以将静态场景编译成八叉树中的潜在可见性集。PVS 的主要原理是预先计算树中的所有节点,其他节点可能从中可见,并将指向它们的指针存储在向量中。当涉及到渲染时,您首先检查相机放置在哪个节点中,然后对节点的 PVS 向量中的所有节点运行视锥体剔除。(Carmack 在 Quake 引擎中使用了类似的东西,但使用二进制空间分区树)

如果您的体素的着色有点复杂,那么执行预深度仅传递也很快,无需写入颜色缓冲区,只需填充深度缓冲区。之后渲染第二遍:禁用写入深度缓冲区并在检查深度缓冲区时仅渲染到颜色缓冲区。因此,您可以避免昂贵的着色器计算,这些计算随后会被更靠近查看器的新片段覆盖。(卡马克在 Quake3 中使用了它)

肯定会加快速度的另一件事是使用实例化。您只需将每个体素的位置以及必要时的比例和其他参数存储到纹理缓冲区对象中。然后,在顶点着色器中,您可以读取要生成的体素的位置并创建体素的实例(即,在顶点缓冲区对象中提供给着色器的立方体)。因此,您只需将 8 个顶点 + 8 个法线(3 *sizeof(float) *8 +3 *sizeof(float) *8 + 用于颜色/纹理等的浮点数)发送一次到 VBO 中的卡,然后只发送TBO 中 Cube(3*sizeof(float)*number of voxels) 实例的位置。

也许通过在 2 个线程中组合所有 3 个步骤来并行化 GPU 和 CPU 之间的事情是可能的,在 CPU 线程中,您检查八叉树 pvs 并更新 TBO 以在下一帧中进行实例化,GPU 线程同时渲染 2在使用上一步中由 CPU 线程创建的 TBO 进行实例化时通过。之后,您切换 TBO。如果相机没有移动,您甚至不必再次进行 CPU 计算。

我感兴趣的另一种树是所谓的 kd-tree,它比八叉树更通用。

PS:对不起我的英语,这不是最清楚的......

于 2012-04-26T23:02:32.983 回答
1

您可以使用第三方库来提高渲染效率。例如,C++ PolyVox 库可以获取体积并以有效的方式为您生成网格。它具有用于减少三角形数量和帮助生成诸如环境光遮蔽之类的东西的内置方法。它周围有一个很好的社区,所以在论坛上获得支持应该很容易。

于 2011-03-05T20:08:56.033 回答
0

您是否为所有立方体使用了一个通用的显示列表?
您是否跳过调用用户不可见的立方体的绘图代码?

于 2010-12-30T15:17:08.510 回答