【GAD翻译馆】利用Cell宽带引擎™的并行Light Pre-Pass 渲染
翻译:赵菁菁(轩语轩缘) 审校:李笑达(DDBC4747)
本文还有一篇草稿,2009第一次在GPU Pro上发表,名为《高级渲染技术》。这篇草稿是我和好朋友Stephen McAuley共同完成的。但里面的有些东西现在我真的不怎么同意了,我没修改太多就发表出来了(只有些许的修正)。
LightPre-Pass渲染器[Engel08, Engel09, Engel09a ]越来越受渲染架构的青睐,已成为当代的实时应用了,具有广泛的动态照明需求。在这篇文章中,我们介绍和描述一种技术,可以在Cell宽带引擎™上用来加速任意三维场景的实时照明,无需向目标应用程序添加任何额外的帧延迟。本文中描述的技术是为即将推出的Blur的PlayStation®3[1]版本开发的,该版本于2010年5月[2]发布。
图 1.Blur截图
1. 概述
随着GPU变得越来越强大,人们希望利用GPU图形以外的用途。这开辟了一个研究领域称为GPGPU(通用图形处理器),各大显卡厂商都在极力研究。例如,所有的NVIDIA® GeForce ® GPU现在都支持PhysX®技术,使物理计算得以在GPU上执行。然而,相反的现象却少了很多——随着系统中CPU的速度和数量的增加,在某些架构上,将某些图形计算从GPU转移到CPU上变得可行。即将发布的硬件,如英特尔的Larrabee,甚至结合了两种形式[ Seiler08 ],这肯定会导致之前只有GPU问题的基于CPU的解决方法越来越受关注。今天,这样的架构是PlayStation®3,其中强大的Cell宽带引擎™从一开始就设计为在处理活动种[ Shippy09 ]支持GPU。本文解释了如何利用Cell宽带引擎™计算light pre-pass渲染引擎环境下的光照。
2. Light Pre-Pass 渲染
在计算机图形学中经常遇到的一个问题是:如何在场景中构建一个可以处理很多动态光线的渲染器。传统的正向渲染不能很好地表现多个光源。例如,如果一个像素着色器被写入最多四个点光源,那么只能绘制四个点光源(没有投光灯)。每增加一次光,我们可以增加像素着色器组合的数量来处理尽可能多的情况,或者我们可以多次渲染该几何体。但这两种解决方案都不可取,因为它们增加了状态更改的次数,并将绘制调用的次数增加到不可控级别。
这个问题的一个流行的解决方案是使用延迟渲染[Deering88 ]。我们不从像素着色器中全部写出点亮的像素,而是把与表面相关的信息写入G缓冲区,包括深度、法向量和材质信息。如下是G缓冲格式示例:
图2. 来自延迟渲染引擎的G缓冲格式示例(插图来自[Valient07])
然后我们利用G缓冲提供的信息,再把灯光融合到场景中。这样一来,许多光线都可以渲染,不需要额外的几何成本或着色器排列。此外,通过为每个光渲染封闭的体积,我们可以确保只对光直接影响的像素进行计算。然而,有了延迟渲染,所有材质必须使用相同的照明方程,只能通过存储在G缓冲中的的渲染属性更改。渲染进入(和读取)这么多缓冲区也会消耗巨大的内存带宽,带宽和MSAA一同增长。
为了解决这些问题,Engel 建议使用light pre-pass渲染器,先在[ Engel08 ]上在线发表,后来发表在[Engel09 ]上,虽然其他人也提出了类似的想法,最近该想法已经用于《神秘海域:德雷克的宝藏》等游戏中:德雷克的财富[Balestra08]。不是渲染出整个的G缓冲,light pre-Pass渲染器存储一个或两个渲染目标的深度和法向量。之后是照明阶段,所有光的属性积累到照明缓冲区中。然后第二次渲染场景,采样照明缓冲区以确定该像素上的照明情况。
使用Blinn-Phong光照模型意味着照明缓冲区的红色、绿色和蓝色通道存储了扩散计算,而我们可以在alpha通道中安装一个镜面,其中的细节在[ Engel09 ]中详述。也就是说,与延迟渲染不同,不同的材质可以按不同方式处理照明值。这增加了灵活性,同时减少了内存带宽成本,我们发现light pre-pass越来越流行,最近许多游戏在各种硬件平台上都使用着。
然而,延迟渲染和light pre-pass 渲染器都存在这么一个事实:照明是在图像空间中进行的,因此几乎不需要光栅化。这使得照明通道从GPU回到CPU的理想候选。Swoboda在[ Swoboda09 ]中,在PLAYSTATION®3和®Cell宽带引擎™上首次用延迟渲染器证明了这一方法,现在我们将他的工作扩展一下,为lightpre-pass渲染器应用类似的技巧。
3. PLAYSTATION®3 与CBE™
索尼计算机娱乐在2006发布了PlayStation 3 。它包含的Cell宽带引擎™由索尼计算机娱乐公司、东芝公司和IBM公司共同开发[Shippy09, Möller08, IBM08]。Cell是PlayStation 3的中央处理单元(CPU)。除了Cell芯片外,PlayStation®3还有GPU,现实合成器,或RSX®。RSX®由NVIDIA 公司开发,本质上是一个改进的GeForce®7800 [Möller08]。图3是架构的高级视图。
图3.PLAYSTATION®3架构(插图来自[Möller08, Perthuis06])
在Cell芯片中,可以找到两种截然不同的处理器。有PowerPC处理器(PPE)和八个[3 ]纯SIMD处理器[Möller08],也叫做协同处理器(SPE),均是高速连接起来的,“令牌环式”总线称为元件互连总线(EIB),见图4。本文中技术的介绍和描述,主要关心的是特殊目的实体的使用,省略了进一步讨论PPE。
图 4.Cell宽带引擎(插图来自[IBM08])
SPE的一个有趣的奇怪之处是它不直接访问主地址空间,而是有自己的内部存储器,称为本地存储。CBE当前实现的本地存储是256KB大小。内存是统一的,不可译也不受保护[Bader06, IBM08],必须包含SPE的程序代码、调用堆栈和任何可能处理的数据。要从主地址空间加载或存储数据,程序员必须显式使用内存流控制器(MFC)。每个SPE拥有自己的MFC,能够排队十六个直接内存访问(DMA)[IBM08]。
由于SPUISA主要操作SIMD定点和浮点的向量运算[IBM09],这很适合处理大量的矢量化数据。它有一个非常大的注册文件(4KB),有助于隐藏流水线的延迟和展开循环,而在容量的本地存储是比较小的,足以让一个程序员通常能够通过高效多缓冲隐藏内存访问的巨大延迟[ 4 ]。要高效地执行SPE上的代码,应该充分发挥SPE的优势。
有关PlayStation®3和Cell宽带引擎™更深入的讨论超出了本文的范围,感兴趣的读者可以参考IBM的网站深入了解Cell芯片更多细节[IBM09],和Möller、海恩斯和霍夫曼描述在[Möller08]中阐述了PlayStation® 3的一些架构。
4. GPU/SPE同步
随着我们目标平台中的处理器数量越来越大,有关这些处理元素执行工作调度的自动化需求也越来越多。这一直持续到游戏开发团队现在,他们围绕作业调度程序的概念建立了自己的游戏和技术[Capcom06]。我们的引擎不例外也沿袭这一趋势,我们提出的GPU / SPE处理器间通信的解决方案与这一技术紧密结合。正是因为这个原因,我们相信我们的解决方案是一个强大的、可行的RSX®/SPE 通信问题解决方案,大家可以很容易地把这一方案融入他们现有的调度框架。为了在SPE上执行片段着色,不会为渲染管线引入不必要的延迟,需要有一定数量的跨GPU和SPE处理器之间的通信。本节我们讨论用于实现这种同步的方法。
每个SPE有几个内存映射I/O(MMIO)寄存器,可用于处理器与其他SPE或PPU间通信。然而,不幸的是,这些不是从RSX®上平凡可写的。需要另一种方法,需要RSX®发信号告知SPES,法线/深度缓冲区的渲染是完整的,它们现在可以开始工作了,无需SPE程序在全部六个SPE上浪费宝贵的处理时间。
向作业调度程序添加作业的时候,作业调度程序是随意在RSX®-映射内存上给出一个地址,该作业依赖这个地址。当调度程序从作业队列中取出下一个作业时,它会检查这个地址,以确保它是写一个RSX®的已知值。如果该值不已知,该作业被跳过,继续从队列中取出下一个作业并处理,如果内存中的位置被写入,那么我们的作业就可以自由运行了。这个依赖关系如图5所示。
图5.RSX® 和 SPE 通信,当法线/深度缓冲区可以处理时RSX®写入一个128字节的值, SPE从相同的位置取出值来获得其开始工作的时间。
确保GPU等待来自SPE的光缓冲问题的解决方案,对于PlayStation®3开发者来说是众所周知的,但不幸的是我们不能在这里透露。感兴趣的PLAYSTATION®3开发者可以可以咨询索尼的官方发展支持网站。
RSX®继续与SPE进行照明计算这样有用的工作是众望所归的。在Blur中,我们很幸运,因为我们有许多附加视图,这些视图不依赖于光缓存,例如平面反射和后视镜(在其他应用程序中,这些应用程序还可能包括阴影缓冲区),如图6所示。如果在RSX®上没有有用的工作可以执行,可能会像[Swoboda09]中那样潜在地进行一帧光照计算(取决于你的内存预算和您的应用程序要求),这种方法还可以降低停转RSX®的可能性。
图 6.RSX®继续做有用的工作,SPE为我们的场景计算动态光照。
5. Pre-Pass
要开始照明pre-pass,我们必须首先建立法线和深度缓冲区。我们以8:8:8:8格式存储视图空间法线,因为我们可以从所选择的硬件上的深度缓冲区读取内容,所以深度不需要单独的目标。我们选择在视图空间中进行照明,因为我们发现它比世界空间更快。
接下来,我们将相关的固体和alpha测试的几何体渲染到缓冲区中。我们只渲染受灯光影响的几何图形——我们根据光线的包围空间剔除所有的绘制调用,同时还引入远裁剪平面(注意,一个简单的空间试验是不够的,我们还需要渲染附近遮挡光圈的物体)。这些剔除方法约减少一半的绘制pre-pass几何图形代价。
当渲染场景时,我们让模板可以用0xff这个参考值写入。模板缓存区事先清除为0x00,为我们屏幕的相关区域屏蔽掉模板缓冲。无论在RSX®还是SPE上渲染光线,这都会使我们能够使用早期的模板以确保我们只照亮相关像素。
我们目前不提供pre-pass或MSAA光缓冲。这存在一些缺点,包括在物体边缘周围的一些照明伪像,以及丧失在主场景中使用深度缓冲作为深度pre-pass的能力(我们用MSAA渲染主场景)。然而,我们发现的伪像极少,绘制light pre-pass MSAA的额外成本大于有深度pre-pass的存储。这仍然是我们将来希望回归的领域。
一旦我们有了法线和深度的缓冲区,我们就可以执行照明。目前,我们使用朗伯漫反射模型,把光线渲染进入8:8:8:8缓冲。这是为了简单和性能,但是以没有镜面反射和照明范围有限为代价。这也意味着照明缓冲区的alpha通道未使用。关于使用的一些想法在进一步工作的章节中进行了解释。
我们维护了一个照明模型的GPU实现方法,供其他平台参考。首先,模板测试设置为“等于”一个引用值0xff,所以我们只渲染在模板缓冲区中标记了的像素。然后,用两种非常不同的方法,用点光源和投光灯来渲染灯光。
点光源渲染和[ Balestra08 ]中的方法一样——帧缓冲区被分割为若干块(tile),我们集合了影响了每块的光线列表(最多八个)。然后我们使用一个对应于它的灯光数的着色器来渲染每一块。这种方法节省了填充率,我们可以不在意点光源的数目,对于每个像素只重建一次视图空间位置和来自法线/深度缓冲区的法线。
点光源使用更标准的方法来绘制灯光的包围空间——在这种情况下是圆锥。我们渲染正面,除非我们在立体空间内,在这种情况下我们才渲染背面。
当深度边界测试在目标硬件上可用时,我们进一步利用这一方法来优化照明代码。深度边界测试将当前片段坐标下的深度缓冲值与给定的最小深度和最大深度值进行比较。如果存储的深度值超出给定范围,则碎片将被丢弃。当画一个点光源或一个光点空间时,我们将深度边界范围设置为光的最小和最大深度范围。
这给出了一个快速、优化的照明模型GPU实现方法。然而,它仍然占我们帧渲染时间很大比例,其图像空间的性质使它成为从GPU卸载到SPE上的完美候选者。
6. 照明SPE程序
本节详细描述执行照明计算的SPE程序。为了尽量将每个子部分置于整体背景下来阐述,我们已经给出了图7,展示了作为整体的SPE程序的高层结构。
图 7.SPE照明程序的高层流。
6.1 原子块决定者
由于720p帧缓冲对内存占用比较大;SPE本地存储的大小限制;PlayStation 3 ®RSX®创建的表面内部格式,我们的照明SPE程序工作在帧缓冲区的上,64×64像素的大小,如图8所示。因此,需要跟踪哪些块可以带到本地存储区进行处理。我们发现实现这一最简单、最并行方式是通过一个自动递增的驻留在主存储器中的块索引。应该指出的是,SPE和RSX®是只有在处理放置到正确的映射内存的资源时才能够有效地合作。
图8. 每个SPE通过内存中自动递增的块索引给自己分配任务。
为了提高效率(和避免缓存线争抢),块索引对齐到128字节边界,填充128个字节大小,与SPES原子单元缓存线的宽度完全匹配(ATO)[IBM08, IBM07]。块的有效地址(EA)由块索引乘上一个块总大小,与帧缓冲区开头地址作和,如方程6.1所示。对于我们选择的块大小,得到的有效地址总是落在16字节的边界上,因为我们的块大小本身是一个16字节的倍数。
(6.1)
6.2. 多缓冲
多缓冲对于几乎所有处理重要数据的SPE程序都是必要的[Bader07],我们的照明方案也不例外。在我们的实现中,我们使用三重缓冲来最小化主存中的法线/深度缓冲区的访问延迟。三重缓冲区中的每个缓冲区都有足够的空间来支持单个工作单元(即:帧缓冲区的一个单独的块)。我们的三重缓冲区中的第一个缓冲区被用作入DMA的目标,它利用自己的标签组,一旦上一个块的块解码过程[ 5 ]完成,DMA就进入这个缓冲区。第二和第三缓冲区用作解码过程的输出目标。除此之外,它们作为照明计算的暂存存储器,是从运行的SPE程序返回主存中的光缓存的源[ 6 ]。这是通过交替使用两个缓冲区来实现的,以便允许输出DMA异步地执行下一块的解码和照明。我们的多缓冲策略的高级视图如图9所示。
图 9. 我们照明SPE程序中的三重缓冲策略。
这里介绍的多缓冲系统非常有效,我们的SPE程序的每帧、每SPU等待数据被传到内存和从内存中传出,平均5μs,这与延迟了程序的执行早应该体。大部分延迟是在程序执行的早期引入的,正如人们所预料的那样。
6.3. 集光
当法线缓冲区和深度模板缓冲区块的输入状态已经完成了,我们可以开始处理。在我们照明之前,我们首先收集影响给定块的光线。我们为每一块构造一个视锥,并将光的包围球剔除到截锥体上。此外,我们还对模板缓冲区进行了剔除。这是一个至关重要的优化,因为它减少了在昂贵的照明阶段所做的工作。
为了执行剔除和照明,我们实际工作在帧缓冲块的子块上,大小为3216像素。在较小区域的剔除更为有效,我们发现在我们的条件下上述大小的子块是最优的。
接下来,我们在深度模板上迭代,以收集每个子块的最小和最大深度值和最小、最大模板值。深度值将形成我们子块视锥体的近和远裁剪平面,模板值允许我们进行一个模板测试,类似于GPU上的早期模具硬件。
在五部分,我们会介绍在渲染pre-pass缓冲区时把0xff写入模板缓冲,因此任何带有0x00模板的像素,都是我们不希望照亮的。然而,我们没有基于每个像素创建模板,而是跳过子块照明,如果最大模板值等于0x00的话(因此整个子块都是0x00)。
一旦子块通过了模板测试,我们就构建了它的视锥。了解了子块的角落位置,通过使用投影矩阵的值,我们可以在距相机一米的固定距离内构造其在视点空间中的位置(见方程6.5)。通过最小和最大视图空间深度值相乘,我们得到了八个顶点,我们可以从中构造出六个平面(见方程6.4,如何利用深度缓冲值构造视图空间z)。
然后,我们分别构造了点光源和投光灯的列表,它们相交于这个视锥。在每个圆台平面上测试每一个光的边界包围球,测试通过点光源添加到点光源列表中,测试通过的投光灯添加到投光灯列表中。
(6.2)
如果没有聚集到光,那么子块将遵循与模板测试失败相同的路径——即跳过光照,将零输出到帧缓冲区。然而,如果至少有一个光确实影响了子块,那么点光源列表和点光源将被传递到我们的照明函数中,以完成工作中最重要的部分。
6.4. 点光源
用于照明的SPE程序是用C编写的,并大量使用SPE特定语言扩展。我们在早期选择了支持内在Si风格的,而不是更高级别的SPU的风格。这是由于近距离映射到下面由编译器生成的操作码[Acton08]。
照明代码对于软件流水循环展开来讲都是一个很好的候选;我们的照明是一次性执行一批16个像素。我们发现,对于我们光照循环的每次迭代,十六个像素浪费的周期非常少,而且我们仍然可以把所需的内容装入4KB(128, 16 字节)的注册文件中[7]。相对较大的像素集产生大量独立指令,相邻指令所引起的延迟几乎完全消除,整体性能大幅度提高(仅受发出指令的数量限制)。非依赖指令彼此交错的结果是指令可用一段时间后才被使用;这个著名的优化技术也有以下副作用:提高奇数和偶数执行管道的指令平衡,因为有更多适合的、无依赖性的指令可以在协同执行单元(SXU)占据一个取出组。我们发现,将像素分成16组,是我们先前的尝试方法的像素吞吐量的三倍,我们之前通过照明四个像素小组简单地模仿RSX®四周。
(6.3)
在任何照明开始之前,重要的是把正确的输入重建到我们在方程6.3里表达的照明方程中。方程6.4演示了如何重建给定像素深度缓冲值的视点空间位置和视锥的近远平面的z分量。当给定视图空间中像素的x和y坐标和视图投影矩阵时,计算视点空间位置的x和y分量同样微不足道。方程6.5显示了这一点。
(6.4)
(6.5)
在HLSL /Cg着色器中,使用饱和的内在功能把值限制到[0..1]范围内是很常见的。为了在SPE上做到这一点,我们觉得这里有一个聪明的技巧值得一提。Day等人介绍了快速饱和/压缩技术,使用SPU的浮点转换指令以实现把一个浮点值限制到各种不同的范围。这取决于与指令发布的范围偏差操作数的组合[Day08]。在流水线循环中,如我们的照明循环,指令计数常常是代码执行速度的主要决定因素,因此我们能够利用这个技巧产生巨大的效果。清单1演示了这一技术。
1 2 3 4 5 | /* HLSL 饱和,限制到 [0..1]. */ qword x = si_cfltu(q,0x20); qword y = si_cuflt(x,0x20); |
清单1. 在两个偶数管道指令中使qword饱和。
我们的照明的GPU实现和SPE实现之间存在一个有趣的区别:从GPU上的默认结构数组(AOS)数据布局切换到SPE上的转置的、SIMD友好的数组结构(SOA)[ 8 ]数据布局。图10说明了数据格式方面差异。通过将数据存储、加载和置乱成一个SOA布局,我们能够在SPE上执行我们更加优化的照明计算。一个令人愉悦的的切换副作用是:生成的C代码外观更像标量,这使得其他程序员 [ Bader06] 更容易遵循。
图 10. 把AoS置乱成SoA.
SPE是只能处理16字节对齐与本地存储相关的写入和读取[Bader06, IBM08, IBM08a]。在SPU存储和负载单元(SLS)读取或写入地址之前,来自所有加载和存储操作的目标首先经过LSLR寄存器的逻辑“与”(当前的CBE实现是设置为0x3ffff)[IBM08,IBM08a]。写入标量值是通过加载本地置乱存储模式实现的。因此,在16字节边界上执行加载和存储是可取的。我们的程序需要法线/深度缓冲区大量的4字节的加载,也需要很多同样大小的对于我们的光缓冲区的写入,我们不再分批处理这些16字节块的加载和存储,为的是消除额外代码的开销,如果在逐像素的基础上执行这些操作,那么就需要这些代码。事实证明,这将大大提高性能,尤其是在存储几乎所有管道气泡都消除的地方。我们将清单2中像素写入代码中的一部分用于一个四像素块:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | qwordc0 = si_cfltu(dif0, 0x20); qwordc1 = si_cfltu(dif1, 0x20); qwordc2 = si_cfltu(dif2, 0x20); qwordc3 = si_cfltu(dif3, 0x20); dif = si_ila(0x8000); qwordscale = si_ilh(0xff00); dif0 = si_mpyhhau(c0, scale, dif); dif1 = si_mpyhhau(c1, scale, dif); dif2 = si_mpyhhau(c2, scale, dif); dif3 = si_mpyhhau(c3, scale, dif); constvector unsigned char _shuf_uint = { 0xc0, 0x00, 0x04, 0x08, 0xc0, 0x10, 0x14, 0x18, 0xc0, 0x00, 0x04, 0x08, 0xc0, 0x10, 0x14, 0x18 }; qwords_uint = ( const qword)_shuf_uint; qword base_addr =si_from_ptr(result); qwordp0_01 = si_shufb(dif0, dif1, s_uint); qwordp0_02 = si_shufb(dif2, dif3, s_uint); qwordp0 = si_selb(p0_01, p0_02, m_00ff); si_stqd(pixel0, base_addr, 0x00); |
清单 2. 像素被从浮点表示转换为32位值,批量处理为16字节的块,并存储。
6.5 投光灯
为了完整性,我们提出了在方程6.6中常用的“投光灯”的计算。
(6.6)
请注意,这与点光源的方程是相同的,在结束处附加一个术语。d是光的方向(与l相反,是从光到点的方向),θ是内锥的角,φ是外锥的角。然而,我们会存储它们光的余弦值,而不是每次都计算。所有点光源和投光灯的所有照明值的每个像素相加,得到6.7的方程。
(6.7)
7.主通道
当SPE计算完了光缓存器,就会通知RSX®可以渲染主通道了。如上所述,这个阶段的同步非常重要——我们不想从不完整的光缓存中读取数据。为了将光缓存与主场景组合起来,我们将它作为像素着色器中的纹理读取。然而,并不是我们场景中的每一个像素都会接收到来自我们pre-pass的光(见上面,我们只将几何渲染到接收到光的pre-pass中),我们在场景中使用了两种着色器技术:一种是从光缓存中采样,另一种则没有。对于前一种技术,每个像素使用其屏幕空间坐标在光缓存器中查找其光照,然后将光值复合为漫射光,如下所示:
(7.1)
通过简单的加法、乘法来混合整个场景的照明看似很有诱惑力,但从上可以看出,这种方法会导致不正确的照明。这是由于我们场景中存在额外的静态照明。
还可以从主通道中的法线缓冲区读取,这意味着从法线贴图读取和从正切空间转换到视图(或世界)空间只发生一次。然而,这也意味着存储在pre-pass中的法线的低精度变得更加明显(每个组件只有8位)。由于这个原因和其他原因,我们没有使用这个方法。
在渲染的最后,我们有许多使用Cell宽带引擎™进行动态光渲染的场景。这不仅为我们的渲染引擎提供了令人兴奋的新的可能性,而且GPU的成本是最小的,大量的工作在CPU上进行。
8. 结论
我们提出了一种方法,将Cell宽带引擎™上RSX®和SPE之间的lightpre-pass渲染工作分开。我们利用这两个组件的有点来达成我们的优势。:RSX®渲染pre-pass集合的光栅性能和SPE计算照明缓冲的向量数学性能。通过在SPE上的并行照明计算,和RSX®上的其他渲染(例如,动态立方体贴图),照明变成免费的,这是一个主要的GPU优化。事实上,即使没有额外的并行化,我们发现,在某些情况下,在进行照明计算时,五个SPE运行精心打造的程序比RSX®效果要好。
图 11.Blur的另一张截图。
随着新架构的出现,我们相信将有越来越多的机会把处理负载从GPU上转移到CPU上。当把GPU和CPU在因特尔Larrabee 上结合起来时,事情将如何发展还有待观察。[ Seiler08 ],但在Cell宽带引擎™上,我们提供的GPU在以下情况中可以大大加快:如延迟照明或通过编写在SPE上运行的自定义CPU实现lightpre-pass渲染。
9. 未来工作
我们所描述的技术可以做很多改进的地方。首先,我们现在忽略了光照模型中的镜面反射。我们建议要么写出到另一个缓冲区,要么如[Engel09]所述,在照明缓冲区的alpha通道中放一个单色反射项。可以通过在法线缓冲区的alpha通道中增加镜面反射强度来控制材料属性。另一个问题是,我们的照明目前是LDR,它存储以8:8:8:8整数格式存储。一种选择是改到16:16:16:16浮点型,但Wilson认为,应该采用CIE LUV色彩空间[ Wilson09 ]。使用这种方法,我们还可以使用一个8:8:8:8缓冲,但颜色的亮度部分使用16位。这一技术在GPU上有问题,因为灯光叠加在一起不再起作用,但在SPE程序中,我们没有这样的问题,这是比较可行的;如果你想实现更多的GPU技术,漫射光的强度也可以存储在apha通道中,如[Valient07 ]所述。
前面的两个建议都包括在照明缓冲区中使用当前未使用的alpha通道。虽然这个字节肯定有很多可能的用途,但我们目前正在研究的一个想法是存储每个像素的雾量。我们认为,如果使用高度雾,这对于更昂贵的雾化方程来说尤其有利。这是向SPE程序[Swoboda09a ]增加值的例子。
考虑到已经完成的工作,包括处理整个法线和深度缓冲,还有额外的渲染工作可以在SPE程序中完成。一个简单的例子是把深度缓冲到向下采样到四分之一分辨率——可以通过MFC异步输出,增加一点SPE程序开销,而且对于许多降低分辨率的效果是有用的,如运动模糊、遮挡剔除甚至屏幕空间环境光遮蔽。可以通过把视图空间的法线和深度合并为一个32位的缓冲,减少对法线深度缓冲的处理量。通过把法线X和Y分量编码进入头两个通道中(或转化为球面坐标),把线性视图空间深度打包进其余的16位。这使我们的SPE程序所需的数据量减半。事实上,这种方法就是我们为最终版本的Blur选择的方法。
最后,我们打算彻底溢出缓冲区的解码,并在编码的法线/深度缓冲区上进行照明,这有几个优点。解码过程可以通过把帧缓冲块中所有像素用简单通道来代替,这将导致整体照明性能的轻微提高,同时节省照明缓冲所需的存储器。然而,这种额外的性能和改进的内存占用是以数学复杂性的增长为代价的,因为派生像素的视图空间位置变得事关重大。这是因为需要考虑编码缓冲区格式对像素的最终视图空间位置的影响。
10. 致谢
首先,我们要真诚地感谢SCEE研组的发Matt Swoboda,他为我们的持续努力奠定基础,并为我们的实现方法提供建议。我们也要感谢SCEE研发组的Colin Hughes,感谢他的帮助和优化建议。
我们也要感谢所有的超级天才,他们组成了BizarreCreations公司的核心技术团队,尤其是Ian Wilson, Paul Malin, LloydWright, Ed Clay, Jose Sanchez, Charlie Birtwistle, Jan van Valburg, Kier Storey,Fengyun Lu, Jason Denton, Dave Hampson, Chris Cookson 以及 Richard Thomas.
11. 参考文献
[Acton08]M. Acton, E. Christensen, “无休SPU的最佳实践,”http://www.insomniacgames.com/tech/articles/0208/insomniac_spu_programming_gdc08.php, 发表于2009.7.2.
[Bader07]D. A. Bader, “Cell 编程小贴士&技巧,”http://www.cc.gatech.edu/~bader/CellProgramming.html, 发表于2009.7.2.
[Balestra08]C. Balestra 和 P. Engstad, 未知的技术:德雷克的宝藏,2008游戏开发者大会上,链接:HTTP:/ / www.naughtydog。COM /公司/出版社/ 202008 /unchartedtechgdc2008.pdf
[Capcom06]Capcom Inc. “MT框架,” http://game.watch.impress.co.jp/docs/20070131/3dlp.htm,
发表于2009.7.3.
[Day08]M. Day, J. Garrett, “更快的SPU压缩,”http://www.insomniacgames.com/tech/articles/0308/faster_spu_clamp.php,发表于2009.7.2.
[Deering88]M. Deering, “三角形处理器和普通矢量着色器:高性能图形的VLSI系统,” SIGGRAPH 1988.
[Engel08]W. Engel, “Light Pre-Pass 渲染器,”
http://diaryofagraphicsprogrammer.blogspot.com/2008/03/light-pre-pass-renderer.html,accessed on 4th July 2009.
[Engel09]W. Engel, “Designing a Renderer for Multiple Lights: The Light Pre-PassRenderer,” in ShaderX7, edited by Wolfgang Engel, Charles River Media, 2008:pp. 655-666.
[Engel09a]W. Engel, “Light Pre-Pass 渲染器 Mach III,” 出现在ACM SIGGRAPH09会议上, 2009.
[IBM08]IBM公司,Cell宽带引擎编程手册1.11版。
[IBM08a]IBM公司,协同处理单元指令集体系结构。
[IBM09]IBM公司。IBM的Cell项目,http://researchweb.watson.ibm.com/cell/home.html
2009年7月4日。
[Möller08]T. Akenine-Möller, E. Haines, N. Hoffman, “Real-Time Rendering 3rd Edition,”978-1-56881-424-7, A.K. Peters Ltd. 2008.
[Perthuis06]C. Perthuis, “PS3图形管线简介,” 欧洲制图学会2006.
[Seiler08]L. Seiler, D. Carmean, E. Sprangle, T. Forsyth, M. Abrash, P. Dubey, S.Junkins, A. Lake, J. Sugerman, R. Cavin, R. Espasa, E. Grochowski, T. Juni, P.Hanrahan, “Larabee: 用于可视化计算的多核x86体系结构,” ACM图形事务,27卷, 三期, ACM SIGGRAPH 2008,2008.8.
[Shippy09]D. Shippy, M. Phipps “新型游戏机:在新Xbox360和Playstation 3内部创建芯片,” 978-0-8065-3101-4, Citadel Press, 2009.
[Swoboda09]M. Swoboda, 延迟照明和后处理的PlayStation® 3,游戏开发者大会2009 ,链接:http://www.technology.scee.net/files/presentations/gdc2009/DeferredLightingandPostProcessingonPS3.ppt
[Swoboda09a]M. Swoboda, 私人信件, 2009.
[Valient07]M. Valient, “《杀戮地带2》中的延迟渲染,” http://www.dimension3.sk/mambo/Download-document/Deferred-Rendering-In-Killzone.php,发表于2009.7.4.
[Wilson09]P. Wilson, “Light Pre-Pass 渲染器:使用CIE Luv 彩色空间,” 发表于在ShaderX7, Wolfgang Engel, CharlesRiver Media编辑, 2009: pp.667-677.
[1]“PlayStation”, “PLAYSTATION”和“PS” 家族徽标是注册商标,“Cell宽带引擎”是索尼计算机娱乐公司的商标,“Blu ray Disc”和“Blu ray Disc”徽标是商标。
[2]Blur的截图表现了动视暴雪公司和Bizarre Creations有限公司的兴趣。
[3] 八个SPE中的一个被锁定以提高芯片的产量,另一个是由索尼的Cell操作系统保留。在PlayStation®3上运行的应用程序实际可以利用六个SPE。
[4] 正如人们所期望的,线性访问模式比随机访问明显好得多。
[5] 关于如何解码,索尼PlayStation®3开发者可以咨询RSX®用户手册。
[6] 我们目前没有对照明结果进行编码,请关注我们未来的工作以了解更多信息。
[7] 在我们的实现中,单个循环中的任何像素都有可能导致寄存器溢出。
[8]SOA组织也称为“并行数组”。
【版权声明】
原文作者未做权利声明,视为共享知识产权进入公共领域,自动获得授权;