镶嵌技术如何提高性能?

10

计算更多的顶点而不是仅从vram中读取更多似乎是一种违反直觉的做法。但如果内存带宽是使曲面细分值得的问题,那么为什么会存在像置换映射这样的东西?在曲面细分着色器中,如果你从纹理中读取,你仍然会访问vram。纹理查找比更多的原始顶点廉价吗?为什么曲面细分很快?

假设您有一个32个顶点扩充的低多边形模型。这比只有8个曲面细分顶点扩充的更高多边形模型更快吗?换句话说,您是否可以线性地获得更高的性能,越多细分曲面?


有没有任何游戏可以用来比较启用/禁用镶嵌细分时的帧率?《古墓丽影》(2013年版)包括细分,但它与更逼真的头发动作(类似于《爱丽丝疯狂回归》的头发动作)相关联,因此帧率最终变慢。 - rcgldr
@rcgldr 我认为你可以使用这个基准测试 https://unigine.com/products/heaven/ - JAre
1
请记住,在支持细分的显卡出现之前,位移贴图被广泛使用。快速细分需要硬件支持,但是一旦有了它,它确实非常高效。 - Bartek Banachewicz
4个回答

8
没有一种方法能在所有情况下都使镶嵌(tessellation)性能更好。不同的利益和权衡在每种用例中都适用。以下是一些可能有助于使镶嵌比替代方案更快的因素:
- **内存带宽:** 现代计算机主要受到内存速度的限制。即使您使用纹理,单次读取的字节数可能仅为4个字节,而不是通常需要存储顶点数据的32个或更多字节。 - **细节级别(LOD):** 使用镶嵌着色器,您可以避免过于详细的区域,同时确保场景的其余部分具有足够的细节。 - **更少的顶点:** 意味着减少了执行顶点着色器以及之前管道的每个阶段的次数。 - **较少的 CPU 开销:** 可能需要较少的绘图调用,特别是如果您不再需要在 CPU 上执行 LOD。
可能还有我忽略的其他因素...

5

在处理器和内存之间总是要进行一定的权衡。Tessellation(细分)是一种可以节省内存和带宽但会牺牲GPU性能的方式。

为什么要使用细分: 使用位移映射的细分可以显著降低场景中动态或多实例对象的内存带宽,但对于静态单个对象则没有太大用处。

假设屏幕上有一个沿着屏幕奔跑的精灵。如果精灵是高细节(超过100万个顶点),那么每次动画程序移动/变形网格时,所有100万个顶点都会被转换并重新加载到GPU中。

然而,如果您使用低细节模型(50-100k个顶点)进行细分和位移,则只需在GPU上存储一次位移图。您更新包含50k个顶点的网格进行动画并且每帧重新加载更少的网格,然后GPU根据已加载的位移图将其细分为4-5百万个虚拟点。

最终结果是您可以获得2-4倍的网格细节,同时只使用1/20的内存带宽。现在想象一下您同时在屏幕上有20-30个这样的精灵。

为什么不应使用细分:为了在逐步添加细节时实现此目的,GPU必须消耗处理能力,以便在开始运行所有其他着色器之前计算每个细分顶点的3D位置。

您需要注意的主要区别是:只有在实例化和/或动画几何体时,这才对您有帮助。

如果您有一个高细节静态网格,它永远不会移动,并且只在屏幕上有一个实例,则上传完整细节的几何体更快。细分只会增加管道复杂度,而不会带来任何好处。

权衡: 使用细分静态网格可以获得轻微的内存带宽优势。因为顶点需要3个浮点坐标才能被GPU理解。但是采样位移图只需要1个固定点数据坐标才能发挥作用。因为位移图针对相邻顶点进行了归一化。所以必须每帧为每个细分顶点计算额外数据。这将消耗着色器时间,如果使用静态网格则不需要此操作。

但是,如果出于LOD目的将细分降低或关闭,则相对于高细节静态网格,它可以为不需要详细信息的对象节省着色器时间。

所以,针对动态/实例化网格来提高细节总是一个好主意。

但对于静态网格或单个网格,则是LOD能力和管道复杂性之间的权衡。远处的高细节网格比打开细分的细分网格消耗更多的计算时间。但近处的高细节网格比打开细分的细分网格消耗更少的计算时间。

考虑到物体越靠近,缓慢增加镶嵌细节比立即用高细节网格替换低细节网格要好得多。因此,如果平滑LOD是一个重要问题,那么一定要选择镶嵌技术。或者使用镶嵌技术到一定程度,然后再用高细节网格替换它。但这只是一个好主意,如果您不担心内存不足,并且始终在GPU上保留两个版本。否则,您将再次烧掉带宽来交换它们。
同样,内存使用和处理器使用之间总是需要权衡。

1
(在OpenGL的背景下) 正如其他人已经提到的,使用镶嵌技术可以被视为在GPU计算时间增加和应用程序与OpenGL之间带宽减少之间进行权衡。
当你思考一下就会明白这是有道理的,如果你不发送所有的顶点,肯定有一些方法可以获取它们的位置。
大多数现代应用程序以某种方式定义模型(一组顶点等等),然后将其发送到GPU。一次性发送,从而抵消了大多数情况下你想要优先选择镶嵌来增加“性能”的用例(性能指更高的帧率/更低的执行时间,我假设)。只要GPU上还有足够的可用内存,就可以这样做。
在动画的情况下,你不必发送修改后的模型顶点替换已经在GPU内存中的信息。大多数现代应用程序使用一组骨骼和权重,甚至可以存在于GPU上。你只需发送一个像时间这样的统一变量,应用程序所需的就是这些。其余的都在GPU上完成。
即使是静态预定义的LOD网格集也可以在进入主显示/渲染循环之前上传到GPU。权衡是你将无法像使用镶嵌那样精细地控制细节的粒度。
如果我们可以在不比使用镶嵌更多地从应用程序发送数据的情况下修改GPU上的数据,为什么或何时我们会想要使用镶嵌呢?
  1. 正如其他人已经指出的那样,绝对控制LOD是一个很好的理由。
  2. 动态内容生成。让GPU在原地添加顶点比从CPU发送整个新网格甚至是应用程序中的新“位”要更有效率(帧/执行时间更快)。
  3. 当您已经填满了GPU上的每一个字节,并且您不能在缓冲区中存储任何其他东西时。

简单总结结论。 镶嵌如何提高性能?

当不可能在开始渲染之前从应用程序定义和上传顶点数据到GPU时。这是唯一需要使用镶嵌的时候。往往情况并非如此。


1

细分网格的优点在于,在有用的地方(靠近摄像机),使用更多的顶点,而在不太有用的地方(远离摄像机)使用更少的顶点。因此,您可以获得更加详细的几何效果,而无需在场景中的所有位置都使用它。


我知道Tessellation具有像你所说的LOD的好处,但我也读到过即使会以完整细节呈现模型,Tessellation也可以提高渲染模型性能。这是真的还是假的?正如我的问题所询问的那样,如果是真的,为什么呢? - Thomas
1
@Blaz:我认为关键在于,在细分之前执行的处理作用于较少数量的顶点,因此工作量较小。稍后它会扩展到完整数量的多边形,因此在细分后的处理步骤上没有节省。 - Ben Voigt
@BenVoigt,您能否回答并进一步解释一下呢?如果您有一个典型的轻量级顶点着色器,只需通过矩阵相乘即可,这在数学上与插值顶点和细分相比成本大致相同。 - Thomas
@BlazArt:细分的重点在于它不会在每个地方都以完整的细节(最大LOD)呈现--远离相机的几何体将以降低的LOD呈现。如果您绕过/禁用了细分,使得所有东西都以完整的LOD呈现,显然就没有任何好处,因为您已经禁用了它。 - Chris Dodd
实际上,我认为细分曲面只在其他因素限制时对性能有价值:CPU受动态LOD限制?细分曲面可以将负载转移到GPU上。集成显卡没有专用内存,BUS带宽严重受限?细分曲面在CPU缓存中生成顶点 => 在BUS上生成高数量的顶点,带宽低。您的显存不足?动态生成顶点,无需预先存储。您需要像草波或水波这样的特效吗?=> 细分曲面使其易于实现且逼真。 - CoffeDeveloper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接