趙鍇源
(四川大學(xué)計(jì)算機(jī)學(xué)院,成都610065)
環(huán)境光遮蔽(AO)能夠近似計(jì)算出物體表面的遮擋程度,并根據(jù)遮擋程度來(lái)調(diào)節(jié)環(huán)境光照的強(qiáng)度,進(jìn)而增強(qiáng)渲染結(jié)果的層次感和明暗對(duì)比。目前實(shí)時(shí)渲染領(lǐng)域常用的AO 算法主要分兩類(lèi):
一類(lèi)是在屏幕空間利用事先生成好的G-Buffer 來(lái)計(jì)算AO。由于該類(lèi)算法只需要處理2D 數(shù)據(jù),計(jì)算量較小,易于在光柵管線上實(shí)現(xiàn),所以早在2007 年就已經(jīng)被Crytek 應(yīng)用在游戲中,即SSAO 算法[1]。而在隨后的幾年中,業(yè)界又不斷對(duì)SSAO 的積分公式和采樣方式進(jìn)行了改進(jìn),從而又衍生出了采樣效率更高,效果更好的基于屏幕空間幾何信息的AO 算法,如:HBAO[2]、VAO[3]和T-SSAO[4]等算法。但是由于屏幕空間的幾何信息只局限于2D 空間,所以這類(lèi)AO 算法無(wú)論怎么改進(jìn)都無(wú)法反映出屏幕空間以外的遮擋情況。
另一類(lèi)是通過(guò)對(duì)儲(chǔ)存了場(chǎng)景的幾何信息的體素?cái)?shù)據(jù)進(jìn)行Ray March 來(lái)計(jì)算AO,如:DFAO[5]和VXAO[6]。這類(lèi)算法由于使用了3D 紋理來(lái)儲(chǔ)存場(chǎng)景的體素化數(shù)據(jù),因此它們?cè)谟?jì)算AO 時(shí)不再缺失屏幕空間以外的遮擋信息。但是由于受到顯存大小和顯卡帶寬的限制,這類(lèi)算法所使用的3D 紋理的分辨率一般都不高,這就使得計(jì)算出的AO 結(jié)果會(huì)比Ground Truth AO 缺少很多細(xì)節(jié)。
而要得到最接近Ground Truth AO 的結(jié)果,最直接的方法便是利用光線追蹤技術(shù)來(lái)計(jì)算3D 場(chǎng)景的AO。通過(guò)使用光線追蹤技術(shù),可以在計(jì)算AO 時(shí)準(zhǔn)確地獲取到3D 場(chǎng)景中任意位置的幾何信息,進(jìn)而使計(jì)算出的AO 結(jié)果也非常準(zhǔn)確。但是在RTX 顯卡面世以前,由于受顯卡性能的限制,實(shí)時(shí)的光線追蹤幾乎是不可能實(shí)現(xiàn)的。而在2018 年NVIDIA 推出了基于圖靈構(gòu)架的RTX 顯卡以后,實(shí)時(shí)光線追蹤便成為了可能。因此,基于RTX 光線追蹤技術(shù),可以實(shí)現(xiàn)出效果更接近Ground Truth AO 的實(shí)時(shí)AO 算法。
雖然NVIDIA 的RTX 顯卡讓實(shí)時(shí)光線追蹤成為可能,但是現(xiàn)階段RTX 顯卡的光線追蹤能力仍比較有限。如表1 展示的便是在RTX2070 的平臺(tái)上,在不使用反走樣的情況下,以1080p 的分辨率,用光線追蹤為65 萬(wàn)面片的場(chǎng)景計(jì)算AO 時(shí),在不同的每像素投線數(shù)下對(duì)應(yīng)的光線追蹤耗時(shí)。從表1 可以看出,當(dāng)每像素投線數(shù)達(dá)到16 條時(shí),光線追蹤耗時(shí)就已經(jīng)有10 毫秒左右,如果再加上陰影和反射等其他光追效果,整個(gè)場(chǎng)景的渲染效率將很難滿足實(shí)時(shí)的要求。
表1 不同每像素投線數(shù)對(duì)應(yīng)的光追耗時(shí)
因此為了保證渲染效率,每幀所能投射的AO 探測(cè)線的數(shù)量非常有限,如此一來(lái)便給AO 計(jì)算帶來(lái)了比較嚴(yán)重的噪聲問(wèn)題,如圖1 所示。而為了解決噪聲問(wèn)題,本文主要從:①提高AO 探測(cè)線的采樣效率;②利用時(shí)相關(guān)性對(duì)AO 計(jì)算的歷史樣本進(jìn)行復(fù)用;③對(duì)AO 結(jié)果進(jìn)行濾波處理這三個(gè)方面入手進(jìn)行處理。
圖1 在低AO投線數(shù)下(每像素16條)的噪聲問(wèn)題
由此引出本文算法的整體思路,如圖2 所示:①獲取場(chǎng)景在當(dāng)前幀的G-Buffer;②根據(jù)當(dāng)前幀和上一幀的G-Buffer 對(duì)屏幕上的每個(gè)像素點(diǎn)進(jìn)行時(shí)間相關(guān)性的檢測(cè),并標(biāo)記出時(shí)間相關(guān)性失效的像素點(diǎn);③在屏幕上的每個(gè)像素點(diǎn),根據(jù)時(shí)間相關(guān)性失效與否,投射不同數(shù)目的探測(cè)線來(lái)計(jì)算AO;④在滿足時(shí)間相關(guān)性的像素點(diǎn)處,累積復(fù)用歷史樣本;⑤根據(jù)累積復(fù)用程度對(duì)結(jié)果進(jìn)行濾波處理。
圖2 算法整體思路
要為屏幕上的每個(gè)像素點(diǎn)生成探測(cè)向量并計(jì)算AO,需要將每個(gè)像素點(diǎn)對(duì)應(yīng)在場(chǎng)景中的坐標(biāo)和法線作為輸入。此外,時(shí)間相關(guān)性檢測(cè)和濾波處理也都需要將場(chǎng)景的深度作為輸入。因此,本文算法的第一階段便是要獲取場(chǎng)景的G-Buffer。
考慮到目前RTX 顯卡的光線追蹤性能仍比較有限,整個(gè)場(chǎng)景的渲染還不能全由光線追蹤來(lái)完成,而是需要光柵管線與光線追蹤管線協(xié)作來(lái)完成渲染。因此,本文算法直接使用光柵管線的G-Buffer 作為輸入。如此一來(lái),當(dāng)光柵管線與光線追蹤管線協(xié)作渲染時(shí),便可以省去額外用光線追蹤計(jì)算G-Buffer 的開(kāi)銷(xiāo)。同時(shí),這樣做也能夠讓本文算法可以直接兼容光柵管線的TAA 反走樣操作,進(jìn)而省去了對(duì)AO 結(jié)果額外做反走樣處理的開(kāi)銷(xiāo)。
在使用光線追蹤技術(shù)計(jì)算AO 之前,需要檢測(cè)每個(gè)像素點(diǎn)的時(shí)間相關(guān)性,以便在光線追蹤時(shí)根據(jù)時(shí)間相關(guān)性失效與否,動(dòng)態(tài)調(diào)整每個(gè)像素點(diǎn)需要投射的AO探測(cè)線的數(shù)量。在本小節(jié),本文只討論針對(duì)靜態(tài)場(chǎng)景的時(shí)間相關(guān)性的檢測(cè)。
本文首先使用重投影技術(shù)[7]計(jì)算出將當(dāng)前幀屏幕像素點(diǎn)重投影到上一幀屏幕的像素坐標(biāo),如式(1)所示。其中,tcur為像素點(diǎn)在當(dāng)前幀的坐標(biāo),Pcur為當(dāng)前幀的投影矩陣,Vcur為當(dāng)前幀的視點(diǎn)矩陣,Vpre為上一幀的視點(diǎn)矩陣,Ppre為上一幀的投影矩陣,tpre為重投影到上一幀屏幕的像素坐標(biāo)。
在得到當(dāng)前幀像素點(diǎn)重投影到上一幀的像素坐標(biāo)后,還需要檢測(cè)重投影的像素坐標(biāo)是否有效,以便排除因?yàn)橐朁c(diǎn)移動(dòng)造成的遮擋而無(wú)法復(fù)用的像素點(diǎn)。檢測(cè)的方法是:比較當(dāng)前像素點(diǎn)的視點(diǎn)深度dcur與其重投影到上一幀的視點(diǎn)深度dpre,當(dāng)兩個(gè)深度的差距很小時(shí),說(shuō)明重投影有效,否則均無(wú)效。檢測(cè)的表達(dá)式如式(2)所示,其中? 是用來(lái)調(diào)節(jié)檢測(cè)嚴(yán)格程度的閾值。
在完成時(shí)間相關(guān)性檢測(cè)后,本文算法會(huì)將通過(guò)檢測(cè)的像素點(diǎn)的重投影坐標(biāo)存入紋理中,而未通過(guò)檢測(cè)的像素點(diǎn)的重投影坐標(biāo)則會(huì)被標(biāo)記為(-1,-1),這樣在隨后復(fù)用歷史樣本的階段就無(wú)需再重新計(jì)算每個(gè)像素點(diǎn)的重投影坐標(biāo)。
本文計(jì)算每個(gè)像素點(diǎn)的AO 值的基本思路是:首先,從G-Buffer 中讀取像素點(diǎn)對(duì)應(yīng)在世界坐標(biāo)下的位置p 和法線n。然后,用光線追蹤的方式,向以p 為起點(diǎn)以n 為中心的半球空間隨機(jī)投射N(xiāo) 條探測(cè)向量。最后根據(jù)式(3)計(jì)算出該像素點(diǎn)對(duì)應(yīng)的AO 值。其中,單位向量ωi表示第i 條探測(cè)向量的朝向。而函數(shù)V 則表示從坐標(biāo)點(diǎn)p 沿方向ωi發(fā)射的探測(cè)向量的可見(jiàn)性,當(dāng)探測(cè)向量被遮擋時(shí)函數(shù)V 返回0,否則返回1。
由于表達(dá)式(3)中含有法線n 與探測(cè)向量ωi夾角的余弦(即,式中的n?ωi),因此越偏離法線n 的探測(cè)向量ωi對(duì)最終AO 結(jié)果的貢獻(xiàn)越小。所以,為了提高探測(cè)向量對(duì)最終結(jié)果的貢獻(xiàn)率,本文算法使用了概率按n與ωi夾角的余弦分布的隨機(jī)向量。生成以z 軸為中心的且概率按n 與ωi夾角的余弦分布的隨機(jī)向量的表達(dá)式如式(4),其中ξ1和ξ2是一對(duì)相互獨(dú)立的且取值在[0,1)間的均勻隨機(jī)數(shù),而本文算法是使用Halton 序列來(lái)生成這對(duì)隨機(jī)數(shù)的。
在使用了概率按n 與ωi夾角的余弦分布的隨機(jī)探測(cè)向量之后,原式(3)中的余弦項(xiàng)(即,式中的n?ωi)就在計(jì)算中被消掉了,因此最終計(jì)算AO 值的表達(dá)式如式(5)所示。
此外,為了減少AO 探測(cè)的性能開(kāi)銷(xiāo),每個(gè)像素點(diǎn)投射的探測(cè)向量數(shù)N 是根據(jù)該像素點(diǎn)的累積復(fù)用程度來(lái)確定的,當(dāng)累積復(fù)用的歷史樣本數(shù)較低時(shí)N 的取值較大(一般為8-16 條),當(dāng)累積復(fù)用的歷史樣本數(shù)較高時(shí)N 的取值較?。ㄒ话銥?-2 條)。需要說(shuō)明的是,無(wú)論累積復(fù)用的程度有多高,N 的取值都不能為0。因?yàn)橥ㄟ^(guò)重投影復(fù)用的歷史樣本是存在誤差的,而且隨著不斷的累積復(fù)用越舊的歷史樣本積累的誤差越大,所以只有在每幀都加入一些新的探測(cè)樣本,才能保證該幀的累積復(fù)用結(jié)果中的誤差不會(huì)過(guò)大。最后,在完成AO 計(jì)算之后,本文算法會(huì)將每個(gè)像素點(diǎn)使用的探測(cè)向量數(shù)N 保存到一張紋理中,以便在隨后的累積復(fù)用階段可以方便的讀取。
在計(jì)算完新一幀的AO 結(jié)果之后,需要利用重投影技術(shù)將符合時(shí)間相關(guān)性的歷史樣本累積復(fù)用到新的結(jié)果中,以便增加新的結(jié)果中的樣本數(shù),提高AO 結(jié)果的質(zhì)量。由于重投影操作已經(jīng)在時(shí)間相關(guān)性檢測(cè)階段完成,所以本階段僅是對(duì)通過(guò)時(shí)間相關(guān)性檢測(cè)的像素點(diǎn)執(zhí)行累積復(fù)用操作。對(duì)于任意像素點(diǎn)p 累積復(fù)用的表達(dá)式如式(6)所示。
其中,Caccum( p )為像素點(diǎn)p 總的累積樣本數(shù),AOpre(p)為上一幀的累積復(fù)用結(jié)果,N(p)為當(dāng)前幀新增加的探測(cè)樣本數(shù),AOcur(p)為當(dāng)前幀計(jì)算出的AO 值。在完成累積復(fù)用計(jì)算之后,本文算法會(huì)將N(p)的值累加到Caccum中,并將新的Caccum保存到紋理中,以便在下一幀的計(jì)算中使用。此外,同樣是由于通過(guò)重投影復(fù)用的歷史樣本存在誤差,所以為了控制帶有誤差的陳舊歷史樣本在累積復(fù)用結(jié)果中的占比,本文算法將Caccum的最大值限制在了1500。
為了進(jìn)一步改善AO 結(jié)果的質(zhì)量,本文算法對(duì)經(jīng)過(guò)累積復(fù)用處理后的結(jié)果進(jìn)行了濾波。本文使用的濾波算法是Louis Bavoil 和Johan Andersson 在2012 GDC上介紹過(guò)的一種改進(jìn)高斯濾波算法。該濾波算法把中心像素與臨近像素的深度關(guān)系納入考慮,在不需要額外邊界檢測(cè)的情況下,就能做到在濾波的同時(shí)保留物體的邊界細(xì)節(jié)。此外,為了提升濾波效率,該算法采用了變步長(zhǎng)濾波的策略,在靠近中心像素的范圍,以1 倍步長(zhǎng)采樣;而在遠(yuǎn)離中心像素的范圍,以2 倍步長(zhǎng)采樣。因此,在相同采樣數(shù)下,該濾波算法能夠?qū)崿F(xiàn)更大的濾波半徑[8]。
最后,為了避免因過(guò)度濾波而造成的細(xì)節(jié)丟失,本文算法會(huì)根據(jù)累積復(fù)用程度對(duì)濾波結(jié)果和未濾波結(jié)果進(jìn)行線性混合。對(duì)于累積復(fù)用程度較低的區(qū)域,噪聲問(wèn)題非常明顯,則優(yōu)先考慮噪聲問(wèn)題,所以需要濾波結(jié)果的占比高一些;而對(duì)于累積復(fù)用程度較高的區(qū)域,噪聲問(wèn)題已經(jīng)很小,則優(yōu)先考慮保留細(xì)節(jié),所以需要未濾波結(jié)果的占比高一些。
硬件配置:Intel Core i3-4160 CPU 3.60GHz 處理器,8G 內(nèi)存,NVIDIA GeForce RTX-2070 顯卡;
系統(tǒng)配置:Win10(1809),DirectX 12;
場(chǎng)景配置:65 萬(wàn)三角面片的室內(nèi)靜態(tài)場(chǎng)景;
渲染配置:屏幕分辨率1920×1080,開(kāi)啟TAA 反走樣。
(1)在相機(jī)靜止不動(dòng)的情況下,如圖3 所示。整個(gè)屏幕的所有像素點(diǎn)都處于高累積復(fù)用的狀態(tài)。加上生成G-Buffer 的耗時(shí),整個(gè)算法的一幀耗時(shí)僅為2.73 毫秒,fps 達(dá)到366 幀/秒,同時(shí)畫(huà)面質(zhì)量也和Ground Truth AO 非常接近。
(2)當(dāng)相機(jī)漫游場(chǎng)景時(shí),如圖4 所示。在物體的邊界附近,以及新移入視野的物體附近,像素點(diǎn)會(huì)因?yàn)闀r(shí)間相關(guān)性失效而處于低累積復(fù)用的狀態(tài)。此時(shí),為了保證這些區(qū)域的AO 質(zhì)量,需要提高投射的探測(cè)向量數(shù),因此渲染耗時(shí)會(huì)略有增加。加上G-Buffer 的耗時(shí),整個(gè)算法的一幀耗時(shí)為3.10 毫秒,此時(shí)fps 為322 幀/秒。又由于單幀所能增加的探測(cè)向量數(shù)是比較有限的,所以時(shí)間相關(guān)性失效的區(qū)域的AO 質(zhì)量會(huì)略有下降。雖然在相機(jī)漫游狀態(tài)下本文算法的效率和質(zhì)量都有所下降,但下降幅度都不大,其中耗時(shí)僅增加了0.37毫秒左右,而AO 結(jié)果也僅是在局部出現(xiàn)了輕度模糊。由此說(shuō)明,即使在因相機(jī)移動(dòng)畫(huà)面部分區(qū)域的時(shí)間相關(guān)性失效的情況下,本文算法仍比較穩(wěn)定。
本文提出了一種基于RTX 光線追蹤技術(shù)的AO 算法,該算法充分考慮了當(dāng)前幀與歷史幀之間的時(shí)間相關(guān)性,并根據(jù)時(shí)間相關(guān)性動(dòng)態(tài)調(diào)整AO 的探測(cè)、復(fù)用和濾波,進(jìn)而在保證高效率的同時(shí)又能得到高質(zhì)量的AO結(jié)果。實(shí)驗(yàn)表明,本文算法在應(yīng)用于靜態(tài)場(chǎng)景時(shí),無(wú)論相機(jī)處于靜止還是移動(dòng)狀態(tài),都能以較高效率得到較高質(zhì)量的AO 結(jié)果。
圖3 相機(jī)靜止時(shí)的截圖
圖4 相機(jī)漫游時(shí)的截圖
圖5 Ground Truth AO