GPU影像渲染技术升级 光线追踪应用开发更轻松

作者:Peter McGuinness Imagination多媒体技术营销总监

从1968年起迄今,光线追踪的概念已历经超过一个世代的讨论;它一直被视为一项潜力无穷的技术,特别是对娱乐产业的视觉艺术工作者来说,尤其重要。原因在于光线追踪算法是以递归形式开发的,能逼真模拟光线在真实世界的行为,所以艺术工作者毋须特别花功夫,就能轻松取得阴影、反射和间接照明等效果。

但是,这些日常生活中习以为常的效果,必要耗费庞大的资源才能在逐线扫描的渲染(Scanline Rendering)环境中实现。因此,业界正亟需一种实际且具成本效益的方式,以便能轻松取得实时的光线追踪效果。

可惜的是,截至今日,就运算和系统成本来看,光线追踪效果几乎仅限于脱机渲染,或是必须采用非常昂贵且缺乏互动性的高功率系统,才能实现实时渲染功能。事实上,业界一直在等待实际的光线追踪技术出现,也因此去年在美国Anaheim市举行、深具影响力的Siggraph研讨会中,光线追踪议程标题还被戏称为「光线追踪就在未来,遥远的未来」。

但这一年以来,技术进展已有了重大改变!如今市场上已出现一种崭新、完备的实时互动的光线追踪技术,不但能解决这些问题,并可针对游戏机和行动消费装置等广泛应用提供一套可扩充且具成本效益的解决方案。

光线追踪首重渲染系统设计

光线追踪的处理流程很简单:当模型被转换到世界空间(World Space)里面(会利用3D坐标系统来执行模型的动画与操作),一个检视区域(Viewport)会被定义,然后光线便会从相机并透过Viewport中的每个画素位置进行追踪,一直到被模型所占据的空间与最接近的物体相交为止。主要光线(Primary Ray)会决定物体从相机视角的可视性,假设物体和光线有交会,就会产生三条或更多新的光线,包括反射、折射及每个光源的照明光线。

然后,这些次要光线(Secondary Ray)会被追踪和彼此交错,并产生新的光线,一直到与光源交会,或是遇到其他的限制为止。每次反弹,都会为物体表面带来一种颜色,并被加到累积缓冲器中;当所有光线都被解析完成,缓冲器内就会包含最终的影像(图1)。

图1 光线追踪可建构光线在场景中传输的模型

图1 光线追踪可建构光线在场景中传输的模型

一旦模型建立,并定义材料特性和放置光源后,所有的照明效果会此在渲染过程中自动产生。

这个过程与在扫描线渲染器中所产生每一画素真实的照明效果方式完全不同。在扫描线渲染器中,由于世界空间模型在片段渲染开始前便放弃不用,因此所有的照明效果都必须在内容建立过程中撷取,并制成称为光照贴图(Light Map)的特殊用途纹理,然后此纹理会被用来将预先计算好的光照值迭放至对象表面上。

虽然,原则上是有可能以内建的预处理步骤来动态地产生光照贴图,而且也有实际的例子存在,但为了保留可用的运算资源以供其他的渲染效果使用,实时应用通常都是采用预先制作的方式。举例来说,必须在互动系统中动态运算所得的阴影,通常都是藉由须要以多步骤处理场景几何的方式来进行,以便能产生阴影贴图,它的用法与光照贴图类似,都是在最后的渲染步骤中才会被贴上。

此种作法除了耗费运算资源外,还有许多的缺点。由于它须要预测会用到哪些贴图,并将其视为游戏资产予以保留,因此会增加执行应用程序所需的数据大小。除了这些问题外,贴图是利用有限数量的固定分辨率所产生的,因此会有常见的分辨率问题。

要让光线追踪技巧能为一般的应用所采用,必须将一些类似光线追踪的技巧使用在现今的内容产生中间件套件内的脱机光照贴图制作过程中。它们可被用来产生光照贴图制作的输入影像,并提供一种在OpenGL和DirectX等既有的实时渲染系统中以渐进式导入光线追踪技巧的方法,而不必放弃整个原有的架构系统(图2)。这当然是有益的,因为现有的工具与执行时期(Runtime),以及所有开发人员已经知道的先进技巧都能被保留与增强,能为此较新的技巧提供一个冲击最小的移转路径。

图2 PowerVR GR6500方块图

图2 PowerVR GR6500方块图

这能透过将新功能加入Runtime引擎使用的着色程序语言中来达成,以允许任何一种着色器程序在执行期间投射光线。渲染管线是不会改变的,它仍然是立即、逐渐增量及扫描线的渲染方式。现有的主要可视性决定方法仍可保留,但渲染系统会藉由既有的数据结构与方法来增强,以解决光线追踪的问题。

一旦拥有这项功能,并且有足够的Runtime效能,便能放弃预先制作的方法,以简化应用程序开发的工作流程,同时还能显著提升最终结果的视觉质量与动态功能。

光线追踪引发GPU效能不足问题

今日的问题在于,缺乏足够的Runtime效能或太过昂贵,以及互动性非常有限,特别是试图将光线追踪技巧应用在现有的绘图处理器(GPU)硬件上,将会导致严重的效率问题。

它的主要困难点在于,目前的实时渲染系统采用屏幕空间中区域性的数据,并透过平行化来达到效能。此数据与相关执行中的任务是同步的,因此三角形中的邻近画素会在内存中放在一起,同时它们会倾向共享材料特性,使得存取纹理、着色器程序等会较有效率,并易于平行化。但对光线追踪系统来说并不是如此,在此系统,中视觉上相邻的对象可能会在世界空间坐标系统中离得很远,而且光线通常会因为连续反弹而发散,所以,当采用基于GPU的方法运作时,是非常没有效率,而且不切实际的。

沿用既有的数据结构还有另外两个问题:建构和穿越(Traversal)。交互式动画须使用的加速结构(通常是体素化树状结构,亦即Voxelized Tree)要能实时更新,然而目前的更新方法不仅慢,而且可能非常昂贵。同样地,须采用轻量的穿越法,以将从加速结构中取回数据的时间最小化。以下将提出解决这三种问题的解决方案,并说明如何利用新一代GPU硅智财(IP)核心来建置这些技巧。

由于主要目标是把光线追踪功能带到标准的GPU中,因此须要考虑GPU中的基本架构。市场上有许多种GPU,特别是在低阶市场,但一般来说,GPU着色单元都包含单指令多重数据(SIMD)的计算逻辑单元(ALU)数组。在ALU中,任务(也就是一组的运算作业)会透过排程器来分配执行。这些运算,在Imagination的PowerVR架构中被称为实例(Instances),被用来使它们共享一致性(Coherency)特性的程度达到最大化,诸如空间区域性(Spatial Locality)、材质特性等,以便从内存撷取特性数据的效率,以及它们在跨SIMD数组执行的平行效率都能最大化。

克服光线追踪挑战 GPU新增一致性采集单元

在PowerVR架构中,这些数组会被分组为不同的统一着色丛集(USC)。扫描线渲染过程会自然产生高度的一致性,所以数组会持续忙碌地作业,而ALU的延迟和不可避免的内存存取的延迟能透过任务的切换来降低。有许多数据主机(Data Master)会馈送到排程器中,以处理顶点、画素和运算相关的任务,一旦着色运算完成,结果会输出到资料接收器(Data Sink)中,再根据渲染管线中哪一部分会被执行来进一步处理(图3)。

图3 Mads Drøschler利用PowerVR光线追踪技术所制作的影像

图3 Mads Drøschler利用PowerVR光线追踪技术所制作的影像

光线追踪单元(RTU)能加入此清单中,以同时做为数据接收器(Data Sink)和数据主机(Data Master),所以它能同时接收来自着色器的新光线查询,并将光线/三角形交错的结果发配回去,以供着色之用。它包含储存大量的完整光线查询(含用户数据)的缓存器,其附加在「轴向包围盒(AABB) vs. 光线」测试器和「三角形 vs. 光线」测试器等固定功能的SIMD数组上。

重要的是,这里有一个一致性采集单元(Coherence Gathering Unit),能把内存的存取要求组合到两种类型的其中一种的一致性序列:交叉序列和着色序列,然后将其排程处理。交叉序列会排程至SIMD AABB或三角形测试器;着色序列则会送到USC。

交叉序列在运作时会一面生成、同时一面破坏,这代表着一连串同体系的包围体阶层(Bounding Volume Hierarchy, BVH)的节点或三角形会从外部内存串流进来。一开始,这些序列通常都是完整的,因为原始BVH节点横跨场景中的大体积,因此大部分的光线都会持续撞击到它们。当光线的完整序列会从阶层的底部开始测试时,底部节点会从内存中被读取,而硬件会与适当的节点和三角形进行交叉光线。

对于每个撞击的节点,新的交叉序列会动态地产生,而撞击到节点的光线会被放到新的子序列内。如果子序列完全满了(这在BVH上经常会发生),它会被推到一个已经准备好的堆栈中,并立即被处理。如果序列不完整(会发生在树状的较深处,特别是来自USC的散射输入光线),它会被保留在序列快取内,一直到在相同的BVH上有更多的撞击发生为止。在此模式中,序列能有效地代表在动态随机存取内存(DRAM)内的地址,以便未来能开始读取。此作法有一致性采集光线到三维(3D)空间区域的效果,并能动态地在较不容易进行一致性采集的场景区域内消耗这些序列。

此过程会一直以串行的方式持续进行,直到光线穿越三角形叶节点(Leaf Node)为止;当光线不再是任何交叉序列的成员时,最靠近的三角形就会被找到。

这时候,就会产生新的着色序列,但此时它所采集的数据与此三角形相关的着色状态具有一致性。一旦着色序列完整了,它就会成为一项任务,然后会被排程到着色器中去执行。变量(Uniforms)和纹理状态会加载到共享储存器内,着色任务的平行处理便开始执行:每个光线撞击的结果在此任务中都代表着一个着色实例。

此行为与光栅片段着色器的行为是一样的,但着色器具备额外的特性,其能利用PowerVR着色器指令集中新增的指令来产生新的光线,然后将它们以新的光线查询送到RTU。

确保一致性采集作业 GPU采用非阻断式光线追踪

由于一致性采集的关系,RTU会以其数据进入时完全不同的顺序,将光线/三角形的交叉结果回传到着色器。取决于一致性的条件,较早在讯框渲染中进入RTU的光线有可能会最后离开。

这种动态一致性采集的方式有平行化采集光线(而不是画素)的效果,这表示,即使光线是从完全不同的其他画素的光线树而来,也能被收集在一起,以便能最大化场景中所有存在的可用一致性。然后,它会解耦管线,产生能高度容忍延迟的系统,并实现一个非常完整的重新排序的可能性组合。

为了使此作法能产生效果,需要在内嵌于芯片上的高速静态随机存取内存(SRAM)内保留关键之飞行中(In-flight)的光线。任何光线回弹都会谨慎处理,且能保留所有状态,此种设计须采用非阻断式(Non-blocking)的光线追踪模式。

举例来说,典型的深度第一(Depth First)光线追踪着色器通常能投射一条光线,这是为了决定光线交错后的物体的颜色。因为这是重复发生的,每条光线都会产生庞大的着色器状态堆栈,这会使取得足够的传输中光线变得不切实际,因而无法有效地执行一致性采集,而且宝贵的芯片上内存资源将不敷使用。

在非阻断式的模型内,着色器会产生光线,写出所有稍后要解析光线所需的信息,然后将光线发送到RTU中,并且毋须等待结果的完成。然后,当光线在未来某时间点(由于RTU内的一致性采集作业仍在进行,所以无法确定)开始于着色器执行运算时,由于其所传递的色彩讯息,因此它会知道此光线对哪个画素会有贡献及其贡献的程度。此过程会在光线树由上而下一直重复地执行,而且着色器每次着色都可投射多条光线。其关键在于,原始画素中所有发射的光线将以不同的影响因素累积回到画素内,这些影响因素是根据反弹光线撞击到的各个着色器来调变的。

此累积过程会发生在内嵌于芯片上的讯框缓冲累积器(FBA)内存中,它会快取芯片上的画素,并有效地做用为这些画素的运算不可分割的Atomic Read Modify Write浮点加法器。利用非阻断方式所成功建置的渲染器会发现,只有很少数的行为无法轻松地适用于此模型中而已。

SHG算法增强光栅转化器

最后的要素是建构加速结构,此结构必须是一个完全动态的系统,能够用来增强光栅转化器(Rasterizer)。这是在场景阶层产生器(Scene Hierarchy Generator, SHG)内执行的,其中建置了一个能以串流的方式为RTU建立BVH的算法,并直接放在顶点着色器之后。SHG会以从下到上的方式建立AABB阶层,并直接写入DRAM中。

从内部来看,SHG将整个世界视为log2稀疏八元树(Sparse Oct-tree)。它有空间节点的核心概念,也就是在log2 Oct-tree中的一个整数地址,亦即[xyz]和「层级」,这就是该层级立体画素(Voxel)的log2大小。这些3D空间的整数表示法在内嵌于芯片的SRAM上会快速地重新链结,但直到它们重组好之前不会真的离开芯片,然后会被送出,作为AABB BVH的节点。

SHG会从顶点着色器每次读取一个输入的三角形,然后从树的底部开始一直往上,以串流形式将AABB写到DRAM中。SHG算法是根据以下两个假设来进行此良好的行为模式:一、以三角形相对于整体场景的大小来约略代表该区域的三角形密度;二、三角形通常是网格的成员,因此顶点着色器的递交次序中会有一些固有的空间区域性。

利用第一个假设,SHG将比较每个三角形相对于整体场景尺寸的大小,以决定要利用哪个log2层级来将此三角形予以立体画素化。大三角形的log2层级较低,但在树的位置较高,而小三角形的深度较深。此外,「又窄又长」的三角形会被推到较深处,如此才能得到更精细的立体画素,因此稍后的AABB会更有效率地包围(Bounding)(图4)。

图4 单一步骤建立加速数据结构

图4 单一步骤建立加速数据结构

立体画素转化器(Voxelizer)会为从3D立体画素的高速缓存馈入的三角形产生节点。此高速缓存能有效地决定三角形的空间群组--当快取有哈希碰撞(Hash Collision)或溢出时,节点便会产生(此3D快取的方式是建立在上述的第二个假设,它实际运作的效果非常好)。

然后,这些节点会依次拥有一个计算出来的母节点位置,并再透过导入立体画素的高速缓存。此算法会沿着树状持续执行,将群组的AABB写到DRAM中,以供RTU之用。

加速实现光线追踪 混合式渲染技术受青睐

从绘图开发人员的角度来看,如果能够保留所有目前使用的开发流程,包括工具和应用程序编程接口(API),才能将采用光线追踪的技术障碍降至最低。这意味着,不应该将整个流程转换到新的渲染方式(例如前述的主要光线可视性决定法),最好能建立一个混合式系统,此系统采用增量式扫描线算法供可视性决定之用,但可以选择性地加入光线追踪技术,以便能制作特殊效果。

像OpenGL这类的绘图API并没有在单纯的光线追踪渲染器中采用主要光线概念来决定可视性。此功能是透过扫描线光栅算法来执行,它是发生在场景空间坐标系统,在此系统中,光线必须在世界空间中被投射出来。解决此问题的一种方式是,采用被称为延迟着色的多步骤(Multipass)渲染技巧(图5)。

图5 利用延迟着色的新型游戏引擎

图5 利用延迟着色的新型游戏引擎

此技巧常用于游戏引擎的Runtime中,第一步骤是执行可视性决定,接下来第二步骤是执行附加在可视几何上的着色器程序。此技巧的目标是降低着色对象的额外负担,这些对象通常是看不见的,但它也能被用来在混合系统中来投射起始光线。由于第一步骤之后储存的中间讯息包括世界空间坐标及表面法线向量等数据,所以着色器程序已具备所有投射起始光线所需的讯息(图6)。

图6 游戏引擎中的混合式渲染,利用延迟着色G-缓冲器。

图6 游戏引擎中的混合式渲染,利用延迟着色G-缓冲器。

此方法的效益在于只有可见画素才会投射光线,但这也表示开发人员仅能选择特定对象来投射光线,因此能轻松地控制如何使用特效,以及光线应用在什么地方。它还非常适用于现有的游戏引擎Runtime,因此工作流程能保持不变,同时还能保存所有对现有游戏资源的投资。这样的控制流程意味着,有可能渐进地将资产从增量式技巧转移到光线追踪技巧,为开发人员带来顺利移转所需的灵活性(图7?8)。

图7 传统的光栅式渲染技巧不能简单且准确地模拟光线传输

图7 传统的光栅式渲染技巧不能简单且准确地模拟光线传输

图8 无需额外成本,PowerVR光线追踪GPU能提供超真实感的阴影、反射和透明度。

图8 无需额外成本,PowerVR光线追踪GPU能提供超真实感的阴影、反射和透明度。

使用光线追踪 挖掘新颖功能

光线追踪在游戏中最显著的应用是利用Runtime产生的阴影和反射来建立完全动态的光线。由于能将阴影和反射也纳入真实感和互动性的增强之中,因此能免于取样伪影的影响,以及移除对玩家移动自由度的限制。增强的移动自由度是实现虚拟和扩增实境等应用的重要技术,并能为在线购物等领域开启全新的应用方式。

此外,现在开发人员可以拥有过去其他利用传统技巧可能无法实现,或是质量太低的功能。这些功能的一些范例包括:
.透镜效果
简单地在视点和渲染场景间放置一个适当特性的透镜,就能产生景深、鱼眼图或球面像差等效果(若需要,可做为修正之用)。
.立体与柱状透镜显示渲染
近来热门的运算摄影技巧,例如光场渲染,使用者须要产生多个不同视角的影像;若是立体渲染,须用到两个影像,更多影像则用于多视角柱状透镜显示。扫描线渲染会须要多次转换几何到不同检视区域的额外负担,而光线追踪能重复使用这些转换结果,并轻松地从每个所需的视角投射光线(图9)。

图9 利用光线追踪技术可开发物理、透镜扭曲修正和柱状透镜显示渲染等功能。

图9 利用光线追踪技术可开发物理、透镜扭曲修正和柱状透镜显示渲染等功能。

.特定物体的目标渲染
能够透过变换投射在场景的每个区域的光线数量来实现,取决于此场景是否是主要的注意焦点。
.视线计算
这并不能算是一种绘图技巧,但能用来提升游戏中角色的人工智能,透过让它们投射光线,以便能建立其对其他角色或光源的可视性。另一种使用方式是,投射光线还能被用来开发撞击侦测系统。

本文中介绍的硬件光线追踪解决方案已经就绪,适用于开发包括游戏机,和其他消费性装置如手持和行动装置所用的芯片,并能满足其成本与功耗需求。此解决方案具备的效能与特性,再加上低风险的移转路径,对于想要简化内容创作流程,但又能制作更令人惊艳、更具真实感游戏的开发人员来说,是深具吸引力的。随着此技术将于未来几个月推出,光线追踪应用将能很快地在市场上实现。

文章来源:新电子

--电子创新网--
粤ICP备12070055号