蔣莉珍
(桂林航天工業(yè)學(xué)院, 廣西 桂林541001)
用射線(xiàn)跟蹤生成的圖像質(zhì)量比用光柵化高很多[1],一個(gè)典型的例子就是近年來(lái)動(dòng)畫(huà)中大多數(shù)的特技效果都用路徑跟蹤來(lái)完成的。 但是使用射線(xiàn)跟蹤是有挑戰(zhàn)性的實(shí)時(shí)應(yīng)用程序,例如在游戲中的應(yīng)用。首先像包括包圍卷層次(BVH)構(gòu)造、BVH 遍歷、和射線(xiàn)/原始交叉測(cè)試等射線(xiàn)跟蹤算法的步驟的代價(jià)是非常高昂的。 其次在射線(xiàn)跟蹤技術(shù)中采用隨機(jī)抽樣也非常困難,因?yàn)橥ǔP枰獢?shù)百到數(shù)千的樣本,以產(chǎn)生一個(gè)收斂的圖像,這遠(yuǎn)遠(yuǎn)超出了現(xiàn)代實(shí)時(shí)渲染技術(shù)的預(yù)算的計(jì)算范圍,現(xiàn)代實(shí)時(shí)渲染技術(shù)只能按幾個(gè)數(shù)量級(jí)來(lái)進(jìn)行計(jì)算,并且,直到最近,實(shí)時(shí)圖形api 還沒(méi)有光線(xiàn)跟蹤支持使光線(xiàn)追蹤集成在當(dāng)前的游戲中很難被利用。 隨著在DirectX 12 和Vulkan 中射線(xiàn)跟蹤支持的宣布徹底的改變了此前的狀況。 本文主要采用了DirectX 射線(xiàn)追蹤(DXR)并將其集成到UE4 中,這使得可以重用現(xiàn)有的材質(zhì)著色器代碼。
將光線(xiàn)跟蹤框架集成到大型應(yīng)用程序如虛幻引擎中是非常困難的,對(duì)于ue4 來(lái)說(shuō)已經(jīng)算是非常大的構(gòu)架更改了[2]。 將光線(xiàn)追蹤集成到UE4 主要為了實(shí)現(xiàn)的目標(biāo)如下:
(1)性能。 這是UE4 的一個(gè)關(guān)鍵方面,通過(guò)此方面來(lái)判斷光線(xiàn)跟蹤功能是否可以符合用戶(hù)的期望。 通過(guò)使用現(xiàn)有的基于光柵化的技術(shù)計(jì)算g 緩沖區(qū),然后通過(guò)對(duì)比可以幫助我們更好進(jìn)行的判斷,在進(jìn)行計(jì)算時(shí)最重要的是射線(xiàn)是用來(lái)計(jì)算特定的通道,如反射或面積光的陰影。
(2)兼容性。 射線(xiàn)跟蹤通過(guò)的輸出與現(xiàn)有的UE4 的著色和后處理管道必須是兼容的。
(3)光的陰影一致。 UE4 使用的陰影模型必須準(zhǔn)確使用光線(xiàn)追蹤來(lái)產(chǎn)生一致的陰影效果。 具體來(lái)說(shuō)時(shí)需要嚴(yán)格遵循相同的數(shù)學(xué)規(guī)則在現(xiàn)有的著色器代碼中對(duì)UE4 提供的各種遮陽(yáng)模型做BRDF 評(píng)估,重要性抽樣,和BRDF 概率分布函數(shù)。
(4)最小化中斷。 現(xiàn)有的UE4 用戶(hù)必須找到易于理解和擴(kuò)展的集成,因此,這些集成必須遵循UE設(shè)計(jì)范例。
(5)多平臺(tái)支持。 最初在UE4 中實(shí)時(shí)光線(xiàn)跟蹤是完全基于DXR,如果需要UE4 的多平臺(tái)特性支持必須設(shè)計(jì)新系統(tǒng),這樣在以后進(jìn)行平臺(tái)移動(dòng)時(shí)就不必過(guò)多的關(guān)注重構(gòu)技術(shù)了。
整合分為兩個(gè)階段。 第一個(gè)階段是原型階段,本文利用了“反射”(《星球大戰(zhàn)》的部分)和“光速”(保時(shí)捷)演示探討了光線(xiàn)跟蹤技術(shù)在計(jì)算機(jī)輔助設(shè)計(jì)中的應(yīng)用。 以此來(lái)幫助我們獲取到了有關(guān)性能、API、集成延遲著色管道渲染硬件接口中需要的更改(RHI)、一個(gè)從每個(gè)硬件的細(xì)節(jié)中抽象出用戶(hù)的薄層平臺(tái)、著色器API 的變化、可擴(kuò)展性等等集成中最具挑戰(zhàn)性的方面的結(jié)論。
在找到第一階段出現(xiàn)的大多數(shù)問(wèn)題的答案后,進(jìn)入第二階段。 這包括對(duì)UE4 高級(jí)版本的重大重寫(xiě)渲染系統(tǒng),除了提供了一個(gè)更好的實(shí)時(shí)光線(xiàn)追蹤的集成,也提升了整體性能提高了著色器API 的可擴(kuò)展性等等各方面的好處[3]。
下面簡(jiǎn)述一下在高層次上將射線(xiàn)跟蹤集成到基于柵格的實(shí)時(shí)系統(tǒng)中渲染引擎的幾個(gè)步驟:(1)注冊(cè)將被ray 跟蹤的幾何圖形這樣保證了當(dāng)圖形改變時(shí)可以加速結(jié)構(gòu)可以建立或更新。 (2)創(chuàng)建命中著色器,使任何時(shí)候的射線(xiàn)擊中一塊幾何圖形,都可以像在基于柵格化的渲染計(jì)算它的材料參數(shù)。 (3)創(chuàng)建光線(xiàn)生成著色器,跟蹤陰影反射等各種用途的光線(xiàn)情況。
要理解第一步,首先要理解由DirectX 射線(xiàn)跟蹤API 公開(kāi)的兩級(jí)加速結(jié)構(gòu)(AS)。 在DXR 中兩種類(lèi)型的加速結(jié)構(gòu)形成了一個(gè)兩級(jí)層次結(jié)構(gòu):頂級(jí)加速結(jié)構(gòu)(TLAS)和底層加速結(jié)構(gòu)(BLAS)[4]。 如圖1 所示,TLAS 構(gòu)建在一組實(shí)例之上,并且每個(gè)實(shí)例都有一個(gè)有自己的變換矩陣和指向BLAS 的指針。 每個(gè)BLAS 都建立在一組幾何原語(yǔ)之上,幾何原語(yǔ)可以是三角形,也可以是AABBS,這些其中AABBS 被用來(lái)封裝自定義幾何圖形,由于沿著射線(xiàn)可以找到AABBS 所以這些幾何圖形將使用自定義交叉著色器在加速結(jié)構(gòu)遍歷過(guò)程中進(jìn)行交叉。 TLAS 通常為動(dòng)態(tài)場(chǎng)景重建每個(gè)幀,每個(gè)TLAS 為每個(gè)獨(dú)特的幾何圖形至少構(gòu)建一次[5]。 如果幾何圖形是靜態(tài)的,則在初始構(gòu)建之后不需要額外的BLAS 構(gòu)建操作。不過(guò)對(duì)于動(dòng)態(tài)幾何,BLAS 將需要更新或完全重建。當(dāng)輸入原語(yǔ)的數(shù)量發(fā)生變化時(shí),需要重新構(gòu)建完整的BLAS 比如三角形或AABBS 需要添加或刪除。對(duì)于BVH(這是NVIDIA RTX 實(shí)現(xiàn)所使用的)來(lái)說(shuō)BLAS 更新需要一個(gè)refit 操作,其中樹(shù)中的所有AABBS 都從葉子更新到根,但樹(shù)結(jié)構(gòu)保持不變。
圖1 加速結(jié)構(gòu)的兩級(jí)層次結(jié)構(gòu)Fig. 1 A two-level hierarchy of accelerated structures
在實(shí)驗(yàn)UE4 實(shí)現(xiàn)中,擴(kuò)展渲染硬件接口(RHI)的抽象靈感來(lái)自于NVIDIAOptiX API,但略有不同把整個(gè)的抽象做了相應(yīng)的簡(jiǎn)化。 這個(gè)抽象由3 種對(duì)象 類(lèi) 型 組 成: rtScene, rtObject, 和 rtGeometry。rtScene 是由多個(gè)有效的rtObjects 組成的實(shí)例,每個(gè)實(shí)例都指向一個(gè)rtGeometry。 rtScene 封裝了一個(gè)TLAS,而rtGeometry 封裝了多個(gè)BLAS。 rtGeometry和任何指向給定rtGeometry 的rtObject 都可以由多個(gè)部分組成,所有這些都屬于同一個(gè)UE4 原始對(duì)象(靜態(tài)網(wǎng)格或骨架網(wǎng)格)并且共享相同的索引和頂點(diǎn)緩沖區(qū),但是他們可以使用不同的(材質(zhì))點(diǎn)擊著色器。 rtGeometry 本身沒(méi)有與之關(guān)聯(lián)的著色器,因此我們可以在rtObject 部分設(shè)置著色器及其參數(shù)。
引擎材質(zhì)著色系統(tǒng)和RHI 也被擴(kuò)展到支持DXR 中新的射線(xiàn)跟蹤著色器類(lèi)型,在實(shí)驗(yàn)中主要的著色階段為射線(xiàn)生成、最近命中、任意命中、交叉、錯(cuò)過(guò)。 與這些著色器階段的射線(xiàn)跟蹤管道如圖2 所示。 除了最近命中和任何命中的著色器,本文還擴(kuò)展了引擎支持使用現(xiàn)有的頂點(diǎn)著色器(VS)和像素著色器(PS)。 利用了一個(gè)擴(kuò)展開(kāi)源微軟DirectX 的實(shí)用工具編譯器來(lái)提供一種從預(yù)編譯的VS 和PS的DXIL 表示生成最近命中和任意命中著色器的機(jī)制。 此實(shí)用程序?qū)S 代碼、輸入組裝階段的輸入布局(包括頂點(diǎn)和索引緩沖區(qū)格式和步長(zhǎng))和PS 代碼作為輸入。 給定這個(gè)輸入,它可以生成執(zhí)行索引緩沖區(qū)提取、頂點(diǎn)屬性提取、格式化的最優(yōu)代碼,接下來(lái)是VS 求值(對(duì)于三角形中的三個(gè)頂點(diǎn)),然后使用擊中時(shí)的重心坐標(biāo)插值VS 輸出,其結(jié)果作為輸入提供給PS。 該實(shí)用程序還能夠生成一個(gè)最小的任意點(diǎn)擊著色器來(lái)執(zhí)行alpha 測(cè)試。 這使得引擎中的渲染代碼可以繼續(xù)使用頂點(diǎn)和像素著色器,就好像它們將 被用來(lái)采用光柵化G-buffer 設(shè)置著色器參數(shù)一樣。
圖2 射線(xiàn)跟蹤管道Fig. 2 Ray tracing pipeline
在這個(gè)實(shí)驗(yàn)性的RHI 抽象下的實(shí)現(xiàn)有兩個(gè)額外的職責(zé):編譯射線(xiàn)跟蹤著色器(到特定于gpu 的表示)以及管理著色器綁定表,管理著色器綁定表指向需要用于每個(gè)幾何圖形塊的著色器代碼和著色器參數(shù)。
在引入RTX 和DirectX 射線(xiàn)跟蹤之前,圖形api(用于柵格化和計(jì)算)中現(xiàn)有的管道抽象只需要提供少量的著色器(1 到5 個(gè))來(lái)創(chuàng)建所謂的管道狀態(tài)對(duì)象(PSO),該對(duì)象它封裝了用于輸入著色器的已編譯的特定于機(jī)器的代碼。 這些圖形api 允許在需要時(shí)并行創(chuàng)建許多管道狀態(tài)對(duì)象,每個(gè)對(duì)象用于不同的材質(zhì)或渲染管道。 然而,射線(xiàn)跟蹤管道在很大程度上改變了這一點(diǎn)。 射線(xiàn)跟蹤管道狀態(tài)對(duì)象(RTPSO)必須與所有可能需要在給定場(chǎng)景中執(zhí)行的著色器一起創(chuàng)建,比如當(dāng)一個(gè)射線(xiàn)命中任何對(duì)象時(shí),不管什么樣子的對(duì)象系統(tǒng)都可以執(zhí)行與之相關(guān)聯(lián)的著色器代碼。 在當(dāng)今游戲的復(fù)雜內(nèi)容中,這很容易就意味著成千上萬(wàn)著色器。 編譯數(shù)以千計(jì)的射線(xiàn)跟蹤著色器成機(jī)器碼如果順序進(jìn)行,一個(gè)RTPSO可能非常耗時(shí)。 幸運(yùn)的是,這兩個(gè)DirectX 射線(xiàn)跟蹤和所有其他由RTX expose 啟用的NVIDIA 射線(xiàn)跟蹤api 能夠編譯利用當(dāng)今cpu 的多核在并行多射線(xiàn)跟蹤著色機(jī)的機(jī)器碼。 在實(shí)驗(yàn)中UE4 實(shí)現(xiàn)時(shí),可以通過(guò)簡(jiǎn)單地調(diào)度單獨(dú)的任務(wù)來(lái)使用這個(gè)功能,它們各自編譯一個(gè)射線(xiàn)跟蹤著色器或命中組,形成DXR 所謂的集合。 在每一幀,如果沒(méi)有其他著色器編譯任務(wù)已經(jīng)在執(zhí)行,檢查是否存在那種需求但不能用的著色器。 如果找到任何這樣的著色器,我們就開(kāi)始新一輪的著色器編譯任務(wù)。 我們還檢查了每一幀之前是否有著色器編譯任務(wù)已經(jīng)完成。 如果完成了創(chuàng)建了一個(gè)新的RTPSO,替換了之前的RTPSO。 在任何時(shí)候,一個(gè)RTPSO 都用于一個(gè)幀中的所有DispatchRays()調(diào)用。 任何舊的RTPSO 如果不在幀框架中使用時(shí)都會(huì)被新的RTPSO 所取代。 當(dāng)構(gòu)建TLAS 時(shí),當(dāng)前RTPSO 中尚未提供所需著色器的對(duì)象會(huì)被刪除(跳過(guò))。
這個(gè)表是一個(gè)由多個(gè)記錄組成的內(nèi)存緩沖區(qū),每個(gè)記錄都包含一個(gè)不透明的著色器標(biāo)識(shí)符和一些著色器參數(shù),它們相當(dāng)于DirectX 12 調(diào)用的根表(用于圖形管道繪制或計(jì)算管道調(diào)度)。
由于第一個(gè)實(shí)驗(yàn)實(shí)現(xiàn)的目的是得到每一幀更新場(chǎng)景中每個(gè)對(duì)象的著色器參數(shù),所以著色器綁定表管理很簡(jiǎn)單,就像命令緩沖區(qū)一樣。 著色器綁定表被分配為一個(gè)n 緩沖的線(xiàn)性?xún)?nèi)存緩沖區(qū),大小由場(chǎng)景中的對(duì)象數(shù)量決定。 在每個(gè)框架中,我們利用可見(jiàn)的GPU 以及可以分配緩沖區(qū)的CPU 來(lái)編寫(xiě)整個(gè)著色器綁定表,然后我們將GPU 副本從這個(gè)緩沖區(qū)加入到GPU 本地副本的隊(duì)列中。
最近引入的用于光線(xiàn)跟蹤加速的專(zhuān)用硬件和圖形api 中添加的光線(xiàn)跟蹤進(jìn)行創(chuàng)新,并嘗試一種混合呈現(xiàn)的新方法,將柵格化和光線(xiàn)跟蹤相結(jié)合。 雖然沒(méi)有進(jìn)行在商業(yè)級(jí)游戲引擎虛幻引擎4 中集成光線(xiàn)追蹤的工程實(shí)踐。 不過(guò)這種創(chuàng)新的重建過(guò)濾器,用于渲染隨機(jī)效果,如光滑的反射、柔和的陰影、環(huán)境遮擋和漫射間接照明,每個(gè)像素只有一條路徑,使這些昂貴的效果在實(shí)時(shí)中應(yīng)用成為可能。 而且已經(jīng)成功地使用混合渲染創(chuàng)建了兩個(gè)電影質(zhì)量的演示雖然演示的片段過(guò)于短促。