首页 > 解决方案 > 在 d3d 11 中渲染多对象场景的正确方法是什么

问题描述

如果我想渲染一个特定的网格,我创建它的顶点/索引数据,创建顶点缓冲区,索引缓冲区,将它们绑定到 IA,设置所需的着色器并调用 context->DrawIndexed。我想渲染多个对象的一种选择是为每个对象循环这个过程,但是在 msdn 上它说“输入程序集(IA):您需要为场景中的每个对象附加每个顶点和索引缓冲区。”。我假设这意味着通过单个 Draw 调用绘制多个对象。

对于顶点缓冲区有一个槽号(假设每个对象的顶点缓冲区都有一个槽),但索引缓冲区没有这样的东西吗?有人可以指出一些应该如何设置的例子吗?

我正在谈论的论文:https ://docs.microsoft.com/en-us/windows/win32/direct3dgetstarted/understand-the-directx-11-2-graphics-pipeline

标签: c++direct3d

解决方案


Direct3D 是一种低级图形 API,因此您可以通过多种方式呈现对象。

基本渲染的一个常见模型是将每个网格组织为顶点缓冲区、索引缓冲区和共享相同材质/表面属性(一组顶点着色器、像素着色器、纹理资源等)的“子集”列表.

有关用于渲染的模型/网格/MeshPart 组织的示例,请参见DirectX 工具包。

例如,这个模型:

微软杯

它由一个 VB、一个 IB 组成,并具有“两个子集”,一个用于带纹理的外部,另一个用于无纹理的内部。因此,此场景需要两次调用DrawIndexed.

如果您想渲染此网格的多个 ( n ) 实例,您将使用相同的 VB、相同的 IB 和相同的纹理资源,但通常顶点着色器会应用变换,以便您可以将其定位在场景中。因此,您将使用纹理调用DrawIndexed n次,不使用纹理调用n次。

对于顶点缓冲区布局和着色器签名的每个组合,您还需要一个输入布局对象,您可以在此处将其安排为一个 IL。

虽然此模型没有任何透明度,但您还需要记住,通常必须在渲染所有不透明子集之后渲染“alpha 混合”子集,才能获得预期的结果,即使移除了 z 缓冲区隐藏表面也是如此。

还有许多其他方法可以优化绘制同一网格的多个副本。例如,您可以使用实例化在一次调用中绘制杯子外部的多个副本,DrawIndexedInstanced然后在第二次调用中绘制杯子的所有内部。请参阅SimpleInstancing。您需要不同的输入布局、顶点着色器和额外的 VB 流来提供和使用实例化数据。

PS:现在大部分游戏调用DrawIndexed了几千上万次,刚开始的时候不用担心优化太多。


推荐阅读