我决定在阅读(前一段时间)之后在三角形列表上构建我的引擎,由于需要较少的绘制调用,索引三角形列表表现更好.今天我偶然发现了0xffffffff,它在DX中被认为是条带切割索引,所以你可以在一次调用中绘制多个条带.这是否意味着三角形列表不再具有卓越的性能?
Luc*_*ius 12
我之前试图回答这个问题但是很难失败.挖了更深的材料我决定再试一次.
始终可以使用简并三角形在单个绘制调用中绘制多个三角形条带.那些是面积为零的三角形.通过简单地重复前一个顶点和下一个条带的第一个顶点来制作条带切割,每个条带间隔添加两个元素(两个零区域三角形).维基百科对此方法有更深入的解释.
Direct3D 10中的新功能是条带切割索引(用于索引几何)和RestartStrip HLSL功能.两者都可以用来代替退化三角形方法,有效地降低带宽成本.(现在只需要一个切割而不是两个索引.)
可以将任何原始列表转换为相等的条带,反之亦然吗?剥离列表转换当然是微不足道的.对于剥离转换的列表,我们必须假设我们可以切割条带.然后我们可以将列表中的每个基元映射到一个基本子条带.(虽然从性能的角度来看这不会有用.)
因此,至少对于三角形基元,条带和列表总是具有相同的表现力.在Direct3D 10条带切割不可能的线条之前,所以它们实际上并没有同样的表现力.
在比较条带和列表时,人们似乎最关注的方面是所需的几何数据量.为了比较我们需要能够计算某个拓扑所需元素数量的方法.
原始列表公式
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
Run Code Online (Sandbox Code Playgroud)
原始条形公式
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)
Run Code Online (Sandbox Code Playgroud)
原始重叠描述了相邻基元共享的元素数量.在经典三角形条带中,三角形使用前一个图元的两个顶点,因此重叠为2.在线条中,线条之间只共享一个顶点,因此重叠为1.使用重叠1的三角形条带当然是理论上可行,但在Direct3D中没有任何代表.
strip cut penalty是启动新子带所需的元素数.这取决于使用的方法.使用条带切割索引,罚分为1,因为一个索引用于分隔两个条带.使用退化三角形时,惩罚将是两个,因为我们需要两个零区域三角形用于条带切割.__CODE__描述了当我们需要__CODE__相邻条带之间的元素时的分隔元素的总和.
从这些公式中我们可以推断出它取决于哪种方法需要最小空间的几何形状.
这是许多人似乎忽略的一个方面,尽管它可能是最初有条带的最重要的论据.在如此低的水平上缓存变得非常重要.我不会详细介绍,因为我不知道任何确切的数字,但条带的一个重要特性是数据的高时间局部性.
当组装新基元时,需要从GPU存储器中提取每个顶点.对于三角形,这必须进行三次.现在访问内存通常很慢,这就是处理器使用多级缓存的原因.在最好的情况下,所需的数据已经存储在缓存中,大大减少了内存访问时间.现在对于三角形条带,使用前一个图元的最后两个顶点,几乎可以保证缓存中已经存在三个顶点中的两个.根据实际的内存/缓存访问惩罚,差异可能是巨大的.
使用条带可能有点单调乏味.正如我之前所说的,将列表转换为条带几乎是微不足道的.问题是通过减少子条的数量将基元列表转换为有效的基元条带.对于简单的程序生成几何(高地地形等),我通常尝试使用条带.我还没有为仲裁原语列表编写转换器.这可能很难.另一方面,它只需要做一次.如果你已经是几何约束,那么它可能值得一试.
Direct3D 10的引入对条带与列表问题没有太大影响.现在线条的表现力相同,数据略有减少.在任何情况下,当使用条带时,如果减少子条带的数量(包括带宽和缓存),则总是获得最大的收益.
在具有变换前和变换后顶点缓存的现代硬件上,三次剥离不是赢得索引三角形列表的胜利.您真正使用三次剥离的唯一时间是非索引基元,这些基元由条带很容易计算的东西生成,例如地形系统.
相反,您应该对索引三角形列表进行顶点缓存优化以获得最佳性能.该霍普算法实现DirectXMesh,或者你可以看看汤姆·福赛斯的替换算法.