在 DirectX 11 中使用索引缓冲区;它是怎么知道的?

Posted

技术标签:

【中文标题】在 DirectX 11 中使用索引缓冲区;它是怎么知道的?【英文标题】:Using Index buffers in DirectX 11; how does it know? 【发布时间】:2017-02-14 17:05:15 【问题描述】:

假设我为两个不同的网格创建了两个顶点缓冲区。

     (I'm assuming creating separate buffers for separate meshes is how it's usually done)

现在,假设我想使用索引缓冲区绘制其中一个网格。 看这本书Practical Rendering and Computation with Direct3D 11,它似乎并不像索引缓冲区的创建以任何方式引用顶点缓冲区,那么索引缓冲区如何知道(在输入组装期间)什么顶点缓冲作用?

我用谷歌搜索了一些没有答案的东西,这让我认为我遗漏了一些明显的东西。

【问题讨论】:

【参考方案1】:

你是对的,索引缓冲区不引用特定的顶点缓冲区。在DrawIndexed 期间,活动索引缓冲区用于为活动顶点缓冲区(您使用 SetIndexBuffer/SetVertexBuffers 设置的缓冲区)提供索引。

【讨论】:

好吧,我没有意识到这一点。那么告诉我,我的假设是否正确,因为您有用于单独网格的单独缓冲区?我知道有一个单独的网格对于某些网格(例如场景中的静态道具等)很有用,但总的来说这是好/坏的做法吗?可以/应该使用多少个有任何限制吗? 您可以用多种不同的方式组织您的 VB/IB。关键问题是您必须能够将每个“网格子集”作为不同的绘图提交,因为材料设置需要在绘图之间更改。您甚至可以将一个 VB 和一个 IB 用于整个级别(hardware limitations 内)。如果您是 DirectX 的新手,您应该做一些简单的事情。顺便说一句,看看DirectX Tool Kit。 @EliasFinoli 最佳实践(从性能角度)是减少 DI 调用的数量,即批处理 - 通过连接它们的 VB/IB 和渲染将共享顶点布局、一些纹理和一些着色器的网格分组在一起他们一通电话。没有通用的最佳批处理策略,这取决于您的场景、目标硬件能力等。其中提到了一些技术here。 @w1ck3dg0ph3r 谢谢你们,现在一切都清楚多了。到目前为止,我们在课程中只在屏幕上绘制了一个矩形,但对我来说这一切如何适用于复杂场景从来没有意义。【参考方案2】:

事实上,Index Buffers 和 Vertex Buffers 是完全独立的。

索引缓冲区将在绘制时知道 VertexBuffer(例如:当两者都绑定到管道时)

您可以将索引缓冲区视为“查找表”,您可以在其中保存要绘制的列表或元素索引。

这也意味着您可以将两个完全“逻辑上不相关”的缓冲区附加到管道并绘制它,没有什么可以阻止您这样做,但您当然会得到一些奇怪的视觉结果。

解耦两者有很多优点,这里有几个例子:

您可以重复使用索引缓冲区(例如,具有相同分辨率的两个移位网格可以共享相同的索引缓冲区)。这可能是一个不错的记忆增益。 您可以自己绘制顶点缓冲区并对每个顶点进行一些处理(例如,为精灵绘制点列表,或将蒙皮/置换应用到流输出缓冲区,然后使用 DrawIndexed 绘制生成的顶点缓冲区)李> 两个顶点/索引缓冲区也可以绑定为 ByteAddressBuffer,因此您还可以在 Compute Shader 中处理几何图形,并构建另一个优化的索引缓冲区,例如剔除三角形,然后使用优化的缓冲区处理索引绘制。使用索引而不是顶点应用这些剔除通常比顶点更快,因为您将移动更少的内存。 这是一个小众案例,但有时我必须将网格绘制为一组三角形,然后绘制为一组线(某种形式的线框)。例如,如果您使用一个 Box,您将不想将对角线绘制为线,因此我有一个共享的 Vertexbuffer 与框顶点,然后一个 IndexBuffer 专用于绘制三角形列表,另一个用于绘制线列表。对于大型模型,这也可以有效地增加内存。

【讨论】:

以上是关于在 DirectX 11 中使用索引缓冲区;它是怎么知道的?的主要内容,如果未能解决你的问题,请参考以下文章

Directx 11 - 是来自顶点缓冲区的所有顶点都推送到顶点着色器还是只是索引的顶点?

DirectX11--深入理解与使用缓冲区资源

DirectX 大型模型 > 64k C++

C++ DirectX 11 从第二个顶点缓冲区渲染问题

Directx 11 前缓冲器

对于 DirectX 11,我不能在每个渲染()中计算缓冲区吗?