在 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 中使用索引缓冲区;它是怎么知道的?的主要内容,如果未能解决你的问题,请参考以下文章