opengl 是否值得通过设置一个用作对象索引的加法逐顶点属性来最小化绘制调用的计数?

kfgdxczn  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(108)

我试图组织绘制调用我的场景资产与许多材料和网格。我认为的策略:

  • 每一种材料都需要一个单独的绘图调用
  • 具有不同变换的相同网格可以组合到一个绘制调用中,该调用具有多个示例数据以传递变换

然而,由于存在许多不同dynamic transformations的不同网格,因此它们不能被组织成一个示例绘制调用。相反,具有不同动态变换的每个网格需要一个绘制调用,从而导致许多绘制调用。

  • dynamic transformation:每帧更新网格的平移、旋转和缩放

如果我使用一个存储缓冲区来保存每个网格的变换,并使用网格的唯一object index索引到存储缓冲区中,以获得相应的变换。但对象索引不能被示例化,因为具有不同动态变换的网格不能被示例化。因此,每个顶点需要一个额外的顶点属性来实现该方法。同时,由于一个网格的图元索引是相同的,因此冗余图元索引数据将占用一些存储器使用。

  • object index:分配给网格的索引,可用于索引到存储缓冲区,以获得网格的变换。
  • the reason why object index should be per vertex:每个网格只需要一个对象索引,但我不能传递每个网格/示例的网格对象索引。因为我想将具有不同转换的网格分组到一个绘制调用中,而这些不同的网格不能在一个绘制调用中示例化,因此对象索引数据不能通过示例数据传递。

这个方法值得实现吗?或者有没有更实用的方法来最小化绘制调用的次数?

e0bqpujr

e0bqpujr1#

因此,你有很多对象需要绘制。其中一些对象使用来自不同对象的不同网格,但有时它们共享相同的底层网格。但无论如何,一组特定的对象都共享相同的顶点格式和源缓冲区( VAO ),以及相同的着色器逻辑和着色器资源。
但这些对象确实有不同的每对象信息。这就是在这样的集合中区分每个对象的地方。你引用变换信息,但实际上,它可能是所有类型的每对象状态(纹理等)。
你的目标是用一个绘制调用来绘制集合中的所有对象,所以你需要一种方法来区分着色器中的不同对象,以及使用这些不同对象的方法。
你最终需要的是给予每个对象一个索引,并给着色器提供一个数组,着色器将使用这个数组来获取索引,并获取每个对象的信息。一个特定对象的所有顶点都需要获得相同的索引,如果两个不同的对象从同一个网格中绘制,那么这两个对象的着色器需要不同的索引。
这就是multi-draw和gl_DrawID的作用。gl_DrawID是GL 4.6的核心,但在被采用为核心之前,它曾作为扩展ARB_shader_draw_parameters使用过一段时间。它是pretty widely available
多重绘制渲染命令允许您通过一个函数调用发出多个绘制调用。这些绘制调用都必须使用相同的原语类型,但您以前已经有过这种限制,所以这不是问题。绘制命令数组中的每个绘制都是按顺序执行的,从第一个到最后一个。
因此,每次绘制都有一个索引,从0到绘制次数。你可以通过gl_DrawID预定义的输入在顶点着色器中访问这个索引。因此,你可以使用这个索引从每个对象的SSBO数组中获取你想要的任何每个对象的信息。
另外,gl_DrawID,以及它的任何后续派生,总是一个动态统一的表达式。一个 * SSBO的数组)、采样器均匀数组或bindless textures数组,你可以使用gl_DrawID或基于它的一些(动态均匀)表达式来访问这样的数组。
那么在这个过程中示例化会发生什么呢?虽然多绘制间接实际上允许每个绘制都有自己的示例计数和基本示例,但示例化会使访问每个对象的信息变得更加复杂。每个绘制索引最初只使用一条每个对象的信息,所以每个绘制命令可以直接使用自己的索引。但如果一个绘制命令可以使用多条每个对象的数据,则每个绘制命令必须知道先前的绘制命令消耗了多少示例。
实际上,这并不难做到,shader_draw_parameters包含解决方案:gl_BaseInstance。multi-draw间接命令同时具有示例计数和基本示例值。示例计数直接Map到gl_InstanceID字段,但基本示例值不会添加到此字段。相反,您可以使用gl_BaseInstance直接访问它。
你可以利用这个来计算一个特定的索引。多重绘制命令中每个绘制的基本示例值需要是之前绘制命令的所有示例计数的总和(包括只绘制1个示例的命令)。因此,你的每个对象的索引不再是gl_DrawID;它是gl_BaseInstance + gl_InstanceID

  • 然而 *,如果你这样做,你就失去了gl_DrawID动态一致的优势。gl_InstanceIDgl_BaseInstance不需要动态一致,所以你不能用它们来索引SSBO或采样器的数组,甚至是无绑定纹理。所以如果你想根据绘制调用来切换纹理,你只能使用数组纹理。

相关问题