c++ - 在 d3d 11 中渲染多对象场景的正确方法是什么
问题描述
如果我想渲染一个特定的网格,我创建它的顶点/索引数据,创建顶点缓冲区,索引缓冲区,将它们绑定到 IA,设置所需的着色器并调用 context->DrawIndexed。我想渲染多个对象的一种选择是为每个对象循环这个过程,但是在 msdn 上它说“输入程序集(IA):您需要为场景中的每个对象附加每个顶点和索引缓冲区。”。我假设这意味着通过单个 Draw 调用绘制多个对象。
对于顶点缓冲区有一个槽号(假设每个对象的顶点缓冲区都有一个槽),但索引缓冲区没有这样的东西吗?有人可以指出一些应该如何设置的例子吗?
解决方案
Direct3D 是一种低级图形 API,因此您可以通过多种方式呈现对象。
基本渲染的一个常见模型是将每个网格组织为顶点缓冲区、索引缓冲区和共享相同材质/表面属性(一组顶点着色器、像素着色器、纹理资源等)的“子集”列表.
有关用于渲染的模型/网格/MeshPart 组织的示例,请参见DirectX 工具包。
例如,这个模型:
它由一个 VB、一个 IB 组成,并具有“两个子集”,一个用于带纹理的外部,另一个用于无纹理的内部。因此,此场景需要两次调用DrawIndexed
.
如果您想渲染此网格的多个 ( n ) 实例,您将使用相同的 VB、相同的 IB 和相同的纹理资源,但通常顶点着色器会应用变换,以便您可以将其定位在场景中。因此,您将使用纹理调用DrawIndexed
n次,不使用纹理调用n次。
对于顶点缓冲区布局和着色器签名的每个组合,您还需要一个输入布局对象,您可以在此处将其安排为一个 IL。
虽然此模型没有任何透明度,但您还需要记住,通常必须在渲染所有不透明子集之后渲染“alpha 混合”子集,才能获得预期的结果,即使移除了 z 缓冲区隐藏表面也是如此。
还有许多其他方法可以优化绘制同一网格的多个副本。例如,您可以使用实例化在一次调用中绘制杯子外部的多个副本,
DrawIndexedInstanced
然后在第二次调用中绘制杯子的所有内部。请参阅SimpleInstancing。您需要不同的输入布局、顶点着色器和额外的 VB 流来提供和使用实例化数据。
PS:现在大部分游戏调用DrawIndexed
了几千上万次,刚开始的时候不用担心优化太多。
推荐阅读
- spring-boot - Spring Boot / RabbitMQ 与 Jackson2JsonMessageConverter 不同的 content_type
- python - 如何将一个队列交错到另一个队列中?
- python - 使用 MPI4PY 从 python 调用使用 MPI 的外部程序
- gitlab - 在 ubuntu 18.04.4LTS 上重新安装 gitlab 后,gitlab-reconfigure 在 redis 上被阻止
- c# - 流式传输时的 LibVLCSharp 记录
- git - Visual Studio 源代码控制没有将 Git 存储库放在正确的位置 - 如何修复?
- gradle - 如何在依赖项块中使用变量进行配置?
- css - CSS如何正确使用带有flex子元素的绝对定位容器?
- java - Gremlin(海王星)的选择性展开值
- c - 原生 C 有共同的符号吗?