OpenGL - 如何渲染许多不同的模型?

时间:2018-04-29 12:01:47

标签: opengl 3d rendering cubes

我目前正在努力寻找一种很好的方法来渲染许多(数千种)略有不同的模型。模型本身是一个简单的立方体,有一些顶点偏移,可以想象一个倾斜的四边形面。每个'块'有一个不同的顶点偏移,所以基本上我有类固醇的体素引擎,因为每个块不是一个完美的立方体,而是一个倾斜的长方体。要渲染此形状,需要48个顶点,但可以切割为24个顶点,因为只有3个面可见。通过索引,我们在12个顶点(每个面4个)。

但是,现在我拥有世界上每个块的顶点,我该如何渲染它们?

我尝试过的事情:

  • 实例渲染。听起来不错,不起作用,因为我的模型不一样。 我可以将远程块简化为多维数据集并使用glDrawArraysInstanced / glDrawElementsInstanced渲染它们。

  • 把所有东西放在一个巨大的VBO中。这比单独渲染每个立方体具有更好的性能,但具有一个大网格的缺点。这是不可取的,因为我需要每个立方体都有不同的纹理,光照等......在这个巨大的网格中选择一个立方体是不可能的。

我知道截头剔除和遮挡剔除,但我已经遇到过一些立方体问题(在128x128世界范围内测试过)。

我的要求:

  1. 绘制数千个模型。

  2. 每个模型都有顶点偏移量,使块更少立方体,存储在另一个VBO中。

  3. 每个块必须是一个单独的对象,因为您应该能够放置/删除块。

  4. 有任何良好的表现建议吗?

2 个答案:

答案 0 :(得分:2)

  

这是不可取的,因为我需要每个立方体都有不同的纹理,光照等......在这个巨大的网格中选择一个立方体是不可能的。

程序员应该避免宣称某些事情“不可能”;它限制了你的想法。

为这些立方体的每个面赋予不同的纹理有许多解决方案。 Minecraft方法使用纹理图集。每个“纹理”实际上只是一个大纹理的子部分,您可以使用纹理坐标来选择特定面部使用的子部分。但是你可以变得更复杂。

Array textures允许更直接的方法来解决此问题。这里,纹理坐标是相同的,但您使用每顶点整数来为面选择正确的纹理。特定面的所有顶点都有一个索引。如果你很聪明,你甚至不需要纹理坐标。您可以在顶点着色器中根据gl_VertexID之类的每个顶点值生成它们。

照明参数的工作方式相同:使用一些每顶点数据从UBO或SSBO中选择参数。

至于“个体对象”位,这只是你如何思考问题的问题。不要混淆玩家心中发生的事情与代码中发生的事情。游戏是一种精心设计的错觉;仅仅因为某些东西对用户来说是一个“单个对象”并不意味着它就是你的渲染引擎。

您需要的是能够修改您的世界数据以删除和添加新块。如果您需要将块显示为“已选择”或其他内容,那么您只需要另一个每块值(如照明参数和纹理索引),它会告诉您是将其绘制为“选定”块还是一个“未经选择”的人。或者您可以重绘特定的选定块。有很多方法可以处理它。

答案 1 :(得分:0)

任何不错的显卡(自2010年左右开始)都能够在闪烁的情况下渲染数百万个顶点。

根据每帧的更改次数,方法会有所不同。换句话说,每帧必须将多少数据传输到GPU。

对于少量更改的情况,将数据存储在一个大的VBO或许多较小的VBO(及其VAO)中,通过制服发送更改,并调用几个glDraw ***,显示类似的表现。不同的硬件行为差别不大。索引数据可以提高速度。

当每个帧中的大多数数据发生变化并且这些更改在着色器中很难或无法完成时,那么您的应用程序将受到内存传输限制。 Streaming是一个很好的建议。