9

在阅读(不久前)索引三角形列表由于需要较少的绘制调用而表现更好之后,我决定在三角形列表上构建我的引擎。今天我偶然发现了 0xffffffff,它在 DX 中被认为是条带切割索引,因此您可以在一次调用中绘制多个条带。这是否意味着三角形列表不再具有优越的性能?

4

2 回答 2

13

可以使用面积为零的退化三角形在单个绘制调用中绘制多个三角形条带。通过简单地重复前一个带的最后一个顶点和下一个带的第一个顶点来进行带切割,每个带中断添加两个元素(两个零面积三角形)。

Direct3D 10 中的新功能是条带切割索引(用于索引几何)和RestartStrip HLSL 函数。两者都可以用来代替退化三角形方法,有效地降低带宽成本。(而不是切割的两个索引只需要一个。)

表现力

可以将任何原始列表转换为相等的条带,反之亦然?带状到列表的转换当然是微不足道的。对于列表到条带的转换,我们必须假设我们可以剪切条带。然后我们可以将列表中的每个基元映射到一个基元子条带,尽管这没有用。

因此,至少对于三角形基元,条带和列表总是具有相同的表现力。在 Direct3D 10 之前,条带在不可能的情况下切割线带,因此它们实际上并没有同样的表现力。

内存和带宽

需要向 GPU 发送多少数据?为了比较这些方法,我们需要能够计算特定拓扑所需的元素数量。

原始列表公式

N ... total number of elements (vertices or indices)
P ... total number of primitives
n ... elements per primitive (point => 1, line => 2, triangle => 3)

N = Pn

原始条带公式

N, P, n ... same as above
S ... total number of sub-strips
o ... primitive overlap
c ... strip cut penalty

N = P(n-o) + So + c(S-1)

图元重叠描述了相邻图元共享的元素数量。在经典的三角形带中,三角形使用前一个图元的两个顶点,因此重叠为 2。在线条之间只有一个顶点共享,因此重叠为 1。使用重叠 1 的三角形带当然是理论上可行,但在 Direct3D 中没有表示。

带切割惩罚是开始一个新的子带所需的元素数量。这取决于使用的方法。使用条带切割索引,惩罚将为 1,因为一个索引用于分隔两个条带。使用退化三角形,惩罚将是两个,因为我们需要两个零面积三角形来进行条形切割。

从这些公式中,我们可以推断出哪种方法需要最少的空间取决于几何。

缓存

条带的一个重要特性是数据的高时间局部性。当一个新的基元被组装起来时,每个顶点都需要从 GPU 内存中获取。对于三角形,这必须做三遍。现在访问内存通常很慢,这就是处理器使用多级缓存的原因。在最好的情况下,所需的数据已经存储在缓存中,从而减少了内存访问时间。现在对于三角形条带,使用前一个图元的最后两个顶点,几乎可以保证三个顶点中的两个已经存在于缓存中。

便于使用

如上所述,将列表转换为条带非常简单。问题是通过减少子条的数量将列表转换为有效的原始条。对于简单的程序生成几何体(例如高场地形),这通常是可以实现的。为现有网格编写转换器可能更困难。

结论

Direct3D 10 的引入对条带与列表问题没有太大影响。现在,线条具有同等的表现力,并略微减少了数据。无论如何,在使用条带时,如果减少子条带的数量,您总是会获得最大的收益。

于 2013-07-29T14:03:40.430 回答
6

在具有转换前和转换后顶点缓存的现代硬件上,三剥离并不是对索引三角形列表的胜利。您真正使用三剥离的唯一时间是由带条计算简单的东西(例如地形系统)生成的非索引图元。

相反,您应该对索引三角形列表进行顶点缓存优化以获得最佳性能。Hoppe 算法是实现DirectXMesh的,或者你可以看看Tom Forsyth 的替代算法。

于 2014-09-30T06:34:22.827 回答