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