【译】Forward+:进一步提升延迟光照水平
Takahiro Harada, Jay McKee, and Jason C.Yang
Advanced Micro Devices, Inc.
摘要
这篇论文介绍了Forward+,一种通过光照剔除和仅存储对像素有贡献的光源来渲染许多光源的方法。Forward+是对传统前向渲染的扩展。在管线中加入了使用GPU运算能力来实现的光线剔除,用来创建光源的列表;该列表被传递给最终渲染的着色器,此着色器可以访问光源相关的所有信息。尽管Forward+增加了最终着色器的工作负担,但是与基于计算的延迟光照相比,它需要更少的内存流量。另外,它规避了延迟技术的主要缺点,即对材质和光照模型的限制。为比较Forward+和延迟光照的性能做了实验。
1. 介绍
近年来,延迟渲染在实时渲染,尤其是游戏领域,已开始流行。延迟技术的主要优点是可以使用许多光源,将光照与几何复杂性解耦,和可管理的着色器组合。然而,延迟技术也有缺点,比如材质多样性的限制,更高的内存和带宽需求,透明物体的处理,和缺乏硬件反走样的支持1。材质的多样性是获得真实渲染结果的关键,对于前向渲染来说这不是问题。但是,前向渲染通常需要设置少量固定数量的光源,用以限制潜在的着色器排列数量的激增,并且需要CPU管理光源和对象。另外,当前游戏主机平台(例如Xbox360)的动态分支性能代价太大,这也就可以理解为何延迟渲染开始变得更有吸引力。
最近的GPU有了更高的性能,更多的ALU能力和灵活性,并且有进行通用计算的能力——与目前的主机平台对比。因此,使用前向渲染来渲染许多光源应该是一个可行的选项,但是,单纯在逐像素渲染中遍历每个光源的方法是不可取的。
我们提出了Forward+:一种通过光源剔除和仅存储对像素有贡献的光源来实现渲染许多光源的方法。在最终的着色器中,光源被逐一评估。以这种方式,我们保留了所有前向渲染的优点,并且获得了渲染大量光源的能力。
本论文首先介绍管线并给出实现的高层级的解释,然后对比Forward+和延迟光照的理论内存流量。
2. 相关工作
前向渲染在实践中对着色时能够使用的光源数量是有限制的2。延迟技术克服了这个问题从而得到了广泛应用,尤其是在游戏主机平台上。延迟渲染器输出G-Buffer为屏幕空间光照存储所有几何信息,这对内存系统产生了压力。延迟光照将光照计算和材质评估解耦来减少内存流量。Andersson3使用GPU的计算能力实现了延迟光照系统,理论上,这种方法可以通过减少内存流量来获得在已有的延迟技术中的最佳性能。
Light-indexed延迟光照使用了稍微不同的方法,它通过存储光源索引而非累加光照组件4。它减少了输出G-buffer的开销,但是在最终着色过程中,需要比延迟光照技术读取更过的数据。这个方法有一些限制:例如,每个像素光源的数量有预定义的最大值。这里建议的方法,Forward+,使用了与上述方法相同的概念,但是通过使用现代GPU的灵活计算能力,克服了上述方法的限制并且减少了后续的内存流量。
3. 方法
Forward+扩展了前向渲染管线,仅在最终着色前添加了一个光照剔除(light-culling)阶段。这条管线由3个阶段组成:depth prepass,光照剔除,和最终着色。另一个修改是光源的数据结构,它必须存储在着色器能够访问的线性缓冲区中,用来进行光照剔除和最终着色。Depth prepass是前向渲染的一个可选项,但是对于Forward+在最终着色阶段减少像素重复绘制来说是必不可少的,对于Forward+来说这个消耗相当大。如果拿depth prepass和延迟技术中使用的G-prepass(全屏几何信息被导出到这里)做对比,前向渲染的depth prepass更加廉价,因为它仅仅填充深度缓存。
3.1. 光照剔除
光照剔除阶段类似于延迟光照的光照累加阶段。替代计算光照组件,光照剔除计算重叠于一个像素上的光源索引的列表。这个光源列表可以为每个像素计算,对于最终着色来说是更好的选择。但是如果我们考虑整个渲染管线的效率的话,这么做是不够高效的。最重要的问题是内存占用和光照剔除阶段的计算效率。因此我们把屏幕分成若干瓦片,并基于每个瓦片计算出光源索引。尽管分片会增加每个瓦片中像素列表的误报,但是它大大减少了内存占用和计算量。代价是光源索引buffer的内存空间和最终着色的效率。如第4章详述的那样,通过使用现代GPU的计算能力,光照剔除可以完全在GPU上实现。因此,整个光照管线全部在GPU上执行。
3.2. 着色
由于光照剔除创建了在每个像素上重叠的光源列表,最终着色遍历此光源列表并且使用为每个光源存储的信息评估材质。如果使用延迟技术,最终着色器无法获取光源位置和颜色。现在,每个材质实例信息可以存储到传递给最终着色器的线性结构的缓冲区,并且可以被访问。因此,由于光照累加和着色同时发生在一个地方,拥有完整的材质和光照信息,在像素质量上的所有限制都被解除了。复杂材质和为了提高视觉质量的更精确光照模型的使用再也不受限制,代价是GPU的计算消耗,它主要由一个像素上(重叠光源的数量×材质开销×光照模型开销)决定。使用这种方法,过多像素重复绘制会降低性能;因此,depth prepass对于最小化最终着色器开销至关重要。
4. 光照剔除实现
建议的渲染管线可以重用现有前向渲染管线的大部分代码,因为它主要是对其进行扩展。基于计算的光照剔除是对此技术的一个重要添加。由于当前GPU和图形API的灵活性,光照剔除可以通过若干方式实现,每种都有优缺点。本章描述两种完全在GPU上的实现。这些方法为每个分片构建光源的列表。尽管他们也可以通过运行额外的内核来为每个像素构建光源列表,但是这会增加计算时间和内存占用。
4.1. 收集法
这种方法在单一的compute shader中构建光源列表,与[And11] 3相似。每个分片执行一个线程组。使用分片在屏幕空间的范围和像素的最大与最小深度值计算出分片的视锥。内核首先使用线程组中所有的线程把一个光源读取到本地寄存器。然后并行检查光源到分片视锥上的重叠性。如果光源重叠,线程就使用本地原子操作将此光源累加到线程本地存储(TLS)中。在一个分片的所有重叠的光源被收集到TLS中以后,就用所有线程将光源信息保存到全局内存中。这种方法在光源不是很多的情况下简单又高效。当有数量非常多的光源时,可以考虑使用离散法。
4.2. 离散法
这种方法分若干步骤创建列表。首先计算一个光源与哪个分片重叠并且把光源和分片的索引数据写入一个缓冲区。这一步通过每个光源执行一个线程来完成。缓冲区的数据(此时根据光源索引排序)需要根据分片索引排序,因为我们想要的是每个分片的光源索引列表。我们使用基数排序,然后运行内核在缓冲区中查找每个分片的开始和结束偏移。
5. 结果和讨论
略
6. 总结
我们提出了Forward+,一种为传统前向渲染管线增加了基于GPU计算的光照剔除阶段的渲染方法,用来处理大量光源。它让我们解除了延迟技术的限制,使我们能够结合前向和延迟技术的优势,实现更好的像素质量。Forward+理论上比基于计算的延迟光照需要更少的内存流量。我们进行了实验证明Forward+比需要消耗内存最少的延迟光照技术还要优秀。
由于最终着色的自由度,未来的工作可以探索许多方法。例如通过发射本地短射线到光源,为场景中的所有光照计算阴影。
参考
-
[Kap10] KAPLANYAN A.: CryENGINE 3: Reaching the speed of light. ACM SIGGRAPH 2010 Courses (2010). 2 ↩
-
[AMHH08] AKENINE-MOLLER T., HAINES E., HOFFMAN N.: Real-Time Rendering, 3 ed. AK Peters, July 2008. 3 ↩
-
[And11] ANDERSSON J.: DirectX 11 Rendering in Battlefield 3. Game Developers Conference (2011). 3, 4 ↩ ↩2
-
[Tre09] TREBILCO D.: Light indexed deferred rendering. In ShaderX7 (2009), Charles River Media. 3 ↩