我决定在阅读(前一段时间)之后在三角形列表上构建我的引擎,因为需要较少的绘制调用,索引三角形列表的性能会更好。今天我偶然发现了0xffffffff,它在DX中被认为是条带切割索引,所以你可以在一次调用中绘制多个条带。这是否意味着三角形列表不再具有卓越的性能?
答案 0 :(得分:11)
可以使用面积为零的degenerate triangles在单个绘图调用中绘制多个三角形条带。通过简单地重复下一个条带的前一个顶点和第一个顶点的最后一个顶点来进行条带切割,每个条带中断添加两个元素(两个零区域三角形)。
Direct3D 10中的新功能是条带切割索引(用于索引几何)和RestartStrip HLSL function。两者都可以用来代替退化三角形方法,有效地降低带宽成本。 (而不是只需要一个切割的两个索引。)
是否可以将任何基元列表转换为相等的条带,反之亦然? 剥离列表转换当然是微不足道的。对于 list to strip 转换,我们必须假设我们可以剪切条带。然后我们可以将列表中的每个基元映射到一个基本子条带,尽管这没有用。
因此,至少对于三角形基元,条带和列表总是具有相同的表现力。在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,因为一个索引用于分隔两个条带。使用退化三角形时,惩罚将是两个,因为我们需要两个零区域三角形用于条带切割。
从这些公式我们可以推断出它取决于哪种方法需要最小空间的几何。
条带的一个重要属性是数据的高temporal locality。当组装新基元时,需要从GPU存储器中提取每个顶点。对于三角形,这必须进行三次。现在访问内存通常很慢,这就是处理器使用多级缓存的原因。在最好的情况下,所需的数据已经存储在缓存中,从而减少了内存访问时间。现在对于三角形条带,使用前一个图元的最后两个顶点,几乎可以保证缓存中已经存在三个顶点中的两个。
如上所述,将列表转换为条带非常简单。问题是通过减少子条的数量将列表转换为高效的原始条带。对于简单的程序生成的几何形状(例如,高地地形),这通常是可实现的。为现有网格编写转换器可能会更困难。
Direct3D 10的引入对条带与列表问题没有太大影响。现在线条的表现力相同,数据略有减少。在任何情况下,当使用条带时,如果减少子条的数量,则总是获得最大的收益。
答案 1 :(得分:5)
在具有变换前和变换后vertex caches的现代硬件上,三次剥离不是赢得索引三角形列表的胜利。您真正使用三次剥离的唯一时间是非索引基元,这些基元由条带很容易计算,例如地形系统。
相反,您应该对索引三角形列表进行顶点缓存优化以获得最佳性能。 Hoppe algorithm已实施DirectXMesh,您也可以查看Tom Forsyth's alternative algorithm.