0

您可以使用 IASetVertexBuffers 设置多个顶点缓冲区,但 IASetIndexBuffer 没有复数版本。如果您无法使用单独的索引缓冲区引用它们,那么创建(非交错)多个顶点缓冲区数据的意义何在

(假设我有一个名为 vector3 的结构,带有 3 个浮点 x、y、z)

假设我有一个具有 250.000 个顶点和 1.000.000 个三角形的人类模型;

  • 我将为顶点位置创建一个大小为 250.000 * sizeof(vector3) 的顶点缓冲区,并且,
  • 我将为顶点法线创建另一个大小为 1.000.000 * 3 * sizeof(vector3) 的顶点缓冲区(并且可能为漫反射纹理创建另一个)

我可以设置这些顶点缓冲区,如:

ID3D11Buffer* vbs[2] = { meshHandle->VertexBuffer_Position, meshHandle->VertexBuffer_Normal };
uint strides[] = { Vector3f_size, Vector3f_size };
uint offsets[] = { 0, 0 };
ImmediateContext->IASetVertexBuffers(0, 2, vbs, strides, offsets);

如果 IASetIndexBuffer 仅支持 1 个索引缓冲区,我如何为这些顶点数据设置单独的索引缓冲区

还有(我知道有一些贴花技术,比如从原始模型创建额外的三角形,但是)假设我想在这个人类模型的脸上(比如说前额)渲染一个像疤痕一样的小纹理,这个疤痕只会通过4 个三角形,是否可以创建一个 uv 缓冲区(只有 4 个三角形)并为仅 4 个三角形的位置、法线和 UV 创建 3 个不同的索引缓冲区,但使用相同的原始顶点缓冲区(来自完整人体模型的相同数据)。我不想创建大量的 uv 数据,这些数据永远不会在字符前额旁边渲染(我不想重复使用,为这个辅助纹理层(贴花)重新创建顶点位置数据)

编辑:我意识到我没有正确提出问题,所以我的问题是:

  • 我是否误解了非交错模型结构(是否出于其他原因使用它而不是具有未对齐的顶点组件)?
  • 还是我接近非交错结构错误(有没有办法定义多个非对齐顶点缓冲区并仅用一个索引缓冲区绘制它们)?
4

1 回答 1

0

一次不能超过索引缓冲区绑定的原因是因为在调用 DrawIndexed 时需要指定固定数量的图元。

因此,在您的示例中,如果您有一个具有 3000 个基元的索引缓冲区和另一个具有 12000 个基元的索引缓冲区,则管道将不知道如何将第一组与第二组匹配。

如果某些顶点数据(主要是位置)最终需要在您的顶点缓冲区中复制通常是正常的,因为您的缓冲区需要具有相同的大小。

索引缓冲区用作“查找表”,因此您跨顶点缓冲区的数据需要保持一致。

非交错模型结构有很多优点:

如果您需要多次绘制模型并且某些绘制不需要属性,则首先使用单独的缓冲区可以带来更好的性能。

例如,当您渲染一个阴影贴图时,您将只需要访问位置,因此在交错模式下,您仍然需要绑定一个大型数据结构并以非连续方式访问元素(Input Assembler 就是这样做的)。在非交错数据的情况下,位置将在内存中连续,因此获取速度会快得多。

此外,非交错允许更轻松地对某些属性进行一些处理,如今在计算着色器中执行一些置换或蒙皮是很常见的,因此在这种情况下,您还可以轻松创建另一个位置+法线缓冲区,对这些属性执行蒙皮和处理后将它们连接到管道中(并且您可以保持 UV 缓冲液完好无损)。

如果要绘制非对齐的顶点缓冲区,则可以改用结构化缓冲区(并在着色器代码中使用 SV_VertexID 和一些自定义查找表)。

于 2021-07-19T09:21:29.860 回答