【问题标题】:OpenGL - How to render many different models?OpenGL - 如何渲染许多不同的模型?
【发布时间】:2018-04-29 12:01:46
【问题描述】:

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

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


我尝试过的:

  • 实例化渲染。听起来不错,因为我的模型不一样,所以不起作用。 我可以将远处的块简化为立方体并使用 glDrawArraysInstanced/glDrawElementsInstanced 渲染它们。

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

我知道平截头体剔除和遮挡剔除,但我面前的一些立方体已经出现问题(在 128x128 世界中测试)。


我的要求:

  1. 画几千个模型。

  2. 每个模型都有顶点偏移,以使块不那么立方体,存储在另一个 VBO 中。

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

有什么好的性能建议吗?

【问题讨论】:

  • 我建议基于块的方法,每个块一个 VBO。此外,您可能根本不应该渲染不可见的三角形(通过在体素变化时仔细生成所述 VBO)。

标签: opengl 3d rendering cubes


【解决方案1】:

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

程序员应该避免宣称某事是“不可能的”;它限制了你的思维。

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

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

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

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

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

【讨论】:

    【解决方案2】:

    任何体面的显卡(大约从 2010 年开始)都能够在眨眼间渲染几百万个顶点。

    方法因每帧的更改次数而异。换句话说,每帧必须将多少数据传输到 GPU。

    对于少量更改的情况,将数据存储在一个大 VBO 或多个较小的 VBO(及其 VAO)中,通过统一发送更改,并调用多个 glDraw***,表现出相似的性能。不同硬件的行为差异不大。索引数据可能会提高速度。

    当大部分数据在每一帧中都发生变化,而这些变化很难或不可能在着色器中完成时,那么您的应用就会受到内存传输的限制。 Streaming 是个好建议。

    【讨论】:

      猜你喜欢
      • 2016-02-14
      • 2013-08-19
      • 2016-10-23
      • 1970-01-01
      • 2013-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多