【Siggraph 2015】Stochastic Screen-Space Reflections

代出自薊北門行
[南北朝][鮑照]
羽檄起邊亭,烽火入咸陽。
征師屯廣武,分兵救朔方。
嚴秋筋竿勁,虜陣精且強。
天子按劍怒,使者遙相望。
雁行緣石徑,魚貫度飛梁。
簫鼓流漢思,旌甲被胡霜。
疾風沖塞起,沙礫自飄揚。
馬毛縮如蝟,角弓不可張。
時危見臣節(jié),世亂識忠良。
投軀報明主,身死為國殤。

今天給各位分享的是寒霜引擎在Siggraph 2015上的Stochastic Screen-Space Reflections算法實現(xiàn),這里是原文鏈接

對這個算法的一些細節(jié)進行一下總結,我們有如下的一些要點:

  1. 整個算法執(zhí)行在屏幕空間,將直接光計算得到的SceneColor作為后續(xù)間接光、反射采樣的輸入,這里可以將這里的SceneColor作為直接光數(shù)據(jù),之后通過屏幕空間采樣得到的數(shù)據(jù)作為間接光數(shù)據(jù),兩者疊加就得到了GI的模擬
  2. 對于每個待計算反射的像素點而言,會在屏幕空間,基于depth數(shù)據(jù)進行ray marching,計算得到交點之后,再從Scene Color貼圖進行采樣
  3. 根據(jù)像素本身的粗糙度,采樣的時候會需要基于不同角度的cone發(fā)射多條射線來獲取數(shù)據(jù),光滑表面cone的角度小,粗糙表面cone的角度大
  4. 當需要發(fā)射射線的數(shù)目變多的時候,整體計算的消耗就會上升,而由于光照數(shù)據(jù)是低頻的,因此可以考慮在相鄰像素之間共用射線采樣結果,從而可以實現(xiàn)整體消耗的節(jié)省
  5. 為了提高raymarching的速度,這里還對depth做了Hi-Z(可以理解為Depth的Mipmap)處理,Hi-Z就類似于四叉樹的節(jié)點,先進行粗粒度的碰撞判斷,如果有碰撞,再做細粒度的判斷

這個算法有如下的一些特點:

  1. 優(yōu)點
    1. 整體計算復雜度與場景無關,且用了Hi-Z來加速,性能比較好
    2. 計算結果比較細膩,通常會跟其他GI算法一起使用,以補足出于性能考慮進行粗糙采樣而缺失的細節(jié)
      1. Hi-Z的精度比較高,因此tracing得到的結果會比較精準,對于接觸點附近的反射而言,可以做到很細膩
    3. 可以處理動態(tài)物體
  2. 缺點
    1. 由于是屏幕空間的算法,因此對于屏幕外的光照數(shù)據(jù)是無感知的,導致的表現(xiàn)就是屏幕外的光照結果無法反應到GI或反射上,即結果的不正確,另外,在鏡頭旋轉的時候也可能會導致光照結果的跳變

本文主要內容框架給出如上,先來看下Motivation

鏡之邊緣概念原畫中存在大量反射性的對象,且不同的對象其反射特性還不一樣,有的光滑,有的模糊。

這里是寒霜會議室的一張真實照片,這張圖片中基本上很少看到非常銳利的反射效果,反而戶外光照的陰影效果倒是占據(jù)著較大的比例,這個結果闡釋了SSR一個此前少有人關注的特性,即過濾局部以及全局反射的specular信息。此外,在這個場景中存在很多非光滑平面的反射,尤其是在反射系數(shù)變化程度較高的地表上。另外,注意看椅子的腳與地面接觸的區(qū)域,還可以發(fā)現(xiàn),越是接近反射平面與被反射物體的接觸點,反射效果越是清晰銳利。

賽車游戲中可能會經(jīng)常見到類似上述圖片的場景效果,在這個效果中可以看到反射效果在垂直方向上存在著拉伸,而且在反射平面上也存在較高頻率的粗糙度與法線的變化

因此,寒霜引擎這邊針對SSR提出了以下一些效果預期:
1.能夠支持清晰與模糊反射效果
2.在接觸區(qū)域應該有比較清晰的反射表現(xiàn)
3.為了提升真實感,應該同樣需要縱向的拉伸效果,當然,如果使用的是microfacet BRDF的話,光照結果其實就已經(jīng)將這個包含在內了
4.希望能夠支持逐像素的粗糙度與法線反射調整

先看看前人工作,這里列舉的都是寒霜認為可能會對他們實現(xiàn)前面預期有幫助的一些工作

先看一下標準的SSR實現(xiàn)方法,這種方法只能應用在鏡面反射中:
1.先計算出反射平面上某個反射點對應的反射向量
2.根據(jù)上面的反射向量對depth buffer進行ray marching
3.Ray marching中遇到的第一個交點就是被反射點,讀取此點的顏色數(shù)據(jù)(這里讀取的數(shù)據(jù)有很多來源,比較常見的是讀取上一幀的color buffer數(shù)據(jù))

殺戮地帶(Killzone Shadow Fall)用了一種不一樣的實現(xiàn)光滑SSR的方法,跟Image Space Gathering類似,他們會先生成一張與屏幕尺寸一致的清晰的反射結果貼圖(使得每個相機視線方向對應的反射點計算得到的uv坐標都能在這個貼圖中找到對應的color),之后會為這張清晰的反射貼圖生成一個blur pyramid,之后根據(jù)像素的粗糙度選擇合適的mip level,通過這種方式可以保證采樣結果不會出現(xiàn)明顯的不連貫,不過這里想要建立起粗糙度跟模糊程度之間的關聯(lián)會比較困難。

此外,這種方法在處理normal map的時候也會存在問題,比如上圖所示,由于模糊的時候只注重粗糙度沒有考慮不同點的法線方向不同,使得采樣的結果只覆蓋了其中某一點的法線而非整個區(qū)域多個法線方向采樣結果的平均值,使得采樣結果存在偏差。

另一個缺陷在于交界處的反射也沒有做到很清晰

前人工作中能夠滿足寒霜前面剔除的所有需求的一個方法是Importance sampling,這里對于反射平面粗糙度的表示不是通過模糊來完成的,而是通過對反射方向進行隨機采樣來直接生成模糊結果。如圖所示,對于一個粗糙的表面,其反射的方向將會更加的分散,而對于一個光滑的表面,其反射的方向就會聚集的多。如果覺得結果依然不夠平滑的話,還可以預先對color buffer進行一次blur操作。

這個方法的問題,在于想要得到較好的效果,就需要進行較多次數(shù)的采樣,從而對性能存在很大的考驗。

寒霜給出的方法結合了filtered importance sampling跟殺戮地帶的reflection方法,既使用隨機采樣方向,又使用了屏幕空間的模糊處理。

其中在Importance sampling處理的時候,發(fā)射的射線數(shù)目非常少,甚至低到每個像素只射出一條線

不過跟importance sampling算法不太一樣的地方在于,這個地方并不直接返回被反射點的顏色數(shù)據(jù),而是將被反射點直接存儲下來,這樣可以方便后面進行resolve pass的時候根據(jù)被反射點的數(shù)據(jù)對相鄰像素進行采樣(即所謂的ray reuse,實際上就是將相鄰像素沿著其對應的法線方向ray marching得到的hit點作為當前點的另一條射線ray marching的結果,通過這樣的數(shù)據(jù)重用降低ray marching消耗,實際上是借用了bilinear filtering的概念)。

同樣,在resolve pass中還會根據(jù)粗糙度來設定出射線為中心的椎體的張角,之后考慮被反射點到反射點的距離,計算出被反射點在椎體對應位置的半徑,并根據(jù)這個數(shù)值來計算mip level做模糊處理,通過這種方式可以有效避免前面所說的blur pyramid對于法線數(shù)據(jù)的污染,同時還能夠在交界處得到較為清晰的反射結果。

下面看下效果展示

下面介紹一下詳細的實現(xiàn)細節(jié),主要分成如下幾個步驟:
1.Tile classification,考慮解決怎么識別屏幕中需要SSR的區(qū)域,并將之劃分成不同的tile
2.Ray allocation,評估每個tile需要的采樣精度,并根據(jù)所需精度自適應的分配各個反射像素所需要的出射光線數(shù)目,
3.ray tracing,這里有兩種方案,對應于不同的計算精度
4.Color resolve,通過前面所說的存儲被反射點數(shù)據(jù)的ray reuse方案來求得反射貼圖
5.Temporal filter,利用前一幀的數(shù)據(jù)來提升反射輸出結果的質量

下面對上述事實步驟進行詳細解析。
寒霜將整個屏幕空間分成多個方形區(qū)域,每個區(qū)域稱之為一個tile。劃分完成之后,就會對每個tile進行評估,計算出這個tile反射所需要的rays count。

這個過程具體是怎么實現(xiàn)的呢:

首先,在項目中,會讓用戶設定每個像素需要出射射線數(shù)目的min/max值,之后計算的結果會按照min/max進行縮放。

其次,在評估中,會對每個tile先試探性的進行一些ray tracing計算,之后根據(jù)計算的結構來評估當前數(shù)目的射線所得到的反射點周邊的顏色復雜程度(可以通過圖像的對比度來表示)。

經(jīng)過上述計算后,可以考慮為那些噪聲多(顏色復雜度高)的tile分配更多的tracing ray,此外,在這個過程中還可以通過進一步的檢測所射出的射線是否與場景中的物體相碰撞來決定是否需要基本放棄對tile中像素使用ray marching。

當知道哪些tile需要進行SSR計算之后,就可以通過一個間接的計算來確定哪些情況需要精確ray tracing,哪些情況需要模糊ray tracing。對于鏡面等較為光滑的反射平面而言,通常需要比較清晰的反射結果,此時會選擇使用精確的HiZ tracing方法,這種方法可以給出反射射線的精確交點;對于那些粗糙度比較高的反射平面而言,通常會用性能比較好的但是反射結果比較粗糙的線性ray tracing方法,這種方式得到的反射結果通常會需要經(jīng)過模糊處理來掩蓋數(shù)據(jù)的瑕疵。

這里來簡單回顧一下HiZ的基本框架,其基本思路是非常簡單的,就是根據(jù)場景的depth buffer,按照min-Z的方式構造一個四叉樹,每個父節(jié)點的深度值都是其所有子節(jié)點中深度值最小的,其結果可以看成是一個pyramid。

先從pyramid中最下面的一層,也就是四叉樹中的葉子結點層開始marching,實際上不論當前是在對哪一層進行marching,其處理方式都是相同的,即沿著射線的方向朝著當前節(jié)點的邊緣走,判定射線與當前節(jié)點是否相交,如果沒有相交,就進入更上一層(相當于加大ray marching step length)進行繼續(xù)比較處理

通過這種方式,可以快速跳過marching過程中的空白區(qū)域

如果在當前節(jié)點的marching過程中檢測到相交,那么就進入到此節(jié)點的四個子節(jié)點的marching流程(相當于縮小ray marching step length),如此循環(huán)往復

直到當前碰撞的level已經(jīng)不可繼續(xù)細分未知,此時碰撞的節(jié)點就是最接近于鏡面的最精細的碰撞點了。

蒙特卡羅算法通過離散的期望求取方式來計算函數(shù)的積分,比如需要對f(x)進行積分,其實就相當于對g(x) = f(x)/p(x)求取期望(也是一個積分,積分項為g(x)*p(x)),期望值可以通過離散的累加來模擬,從而將積分轉換為累加。要想求得較為精確的積分結果,就需要大量的采樣數(shù)據(jù)。

Importance sampling其實是蒙特卡羅積分算法的一種,相對于蒙特卡羅算法,Importance sampling使用的樣本數(shù)要少得多,其方差相對也要小得多。

這里針對BRDF使用Importance sampling,來生成反射采樣方向,理論上來說,任何的BRDF都是可以的,寒霜使用的是GGX。

因為Ray-tracing的成本是非常高的,因此想要做到實時就不能生成過多的反射射線。寒霜這里通過采用Halton sampler方法可以做到在盡可能少的射線數(shù)目的前提下獲得最高的采樣精度,在這個方法中,部分參數(shù)數(shù)值可以提前在CPU中計算好。

經(jīng)典的BRDF Importance sampling方法是通過生成多個半角向量(half-angle vectors,即視角方向ViewDir與光照方向LightDir的中間向量),之后按照反射點的microfacet normal計算對應的反射向量。這里有一個問題,那就是生成的半角向量中,有可能會存在射向反射平面之下的向量,而這些向量顯然是不符合反射計算需求的,因此在這里會進行一次過濾,濾除那些異常向量,經(jīng)過實際驗證,這個濾除的操作對性能的影響基本可以忽略。

此外,還可以如Eric Heitz & Eugene D’Eon指出的那樣,對可見法線的分布情況進行importance sampling,使用這種方法得到的結果具有更少的噪聲(目前寒霜也還沒有嘗試,或者嘗試過暫時沒成功)

生成了多條用于ray tracing的射線之后,就進入color計算階段,最簡單的方法就是根據(jù)射線與depth buffer的交點直接讀取color buffer中的結果,不過這種方式得到的color會有比較高的噪音,想要消除噪音就需要更多的ray tracing,性價比過低。不過,實際上大部分時候,反射表面在各個位置的屬性是比較接近的,且周邊位置的點反射后的可見性也基本上是一樣的,因此可以假裝相鄰像素的射線也是從當前像素發(fā)出,且交點跟從相鄰像素發(fā)出的交點一致(跟直接取用color有什么區(qū)別,沒看出存儲交點跟存儲color的區(qū)別)。

對于相鄰射線與Depth buffer上的交點,并不能直接拿來重用,為了保證得到正確的結果,所有射線對于反射color的貢獻值都需要經(jīng)由當前像素的BRDF加權處理,并需要除以對應的PDF。

結果發(fā)現(xiàn),對這個算法的結果預期過于樂觀,事實證明,相鄰射線的PDF可能跟當前像素的BRDF數(shù)值存在較大差異,從而導致某些地方的f/p變得很尖銳。

這里是一個示例場景,場景中反射平面上各個位置的粗糙度跟法線數(shù)據(jù)是不一樣的。

這是只使用一條射線,讀取交點對應位置的color的作為反射顏色的結果,其中反射color buffer的分辨率為屏幕分辨率的1/2.

這里給出的是在resolve pass使用四條射線(一條精確結果,其余三條是通過ray reuse的方式得到的)獲取color的結果,可以看到,部分位置的反射結果確實變得光滑了,但是地表上的大部分區(qū)域的出現(xiàn)了更為明顯的噪音,總體來說,其結果還不如一條射線計算的結果。

先來回顧一下發(fā)生了什么,首先我們需要計算的是這么一個積分,這是一個常見的散射光強積分公式,其意義為反射輸出數(shù)值等于入射輻射照度經(jīng)過BRDF加權后的半球積分。

將之轉換成蒙特卡羅公式形式,其中BRDF,cos項跟分母匯總的PDF項是整個計算的變量Variance。對所有的樣本進行累加之后,由于前面提到的相鄰像素采樣時Variance分子分母之間的巨大差異,導致此時計算得到的Variance要么過大要么過小,從而使得最終的結果過亮或者過暗。

怎么消除這個問題呢,寒霜給出的解決方案是在分母跟分子乘上同一個值,這個值就是BRDF*cos之后的積分,到這一步為之,整個變換過程還依然是等價的。

之后,將分子所乘的積分項用一個離線計算的常量數(shù)值來代替,這種替代方式是IBL積分公式中常用的方法,因此這個常量值在各位的引擎中可能已經(jīng)存在了(詳情參見Brian Karis在2013 PBR course上的演講內容[Karis13])

之后,繼續(xù)使用蒙特卡羅算法對剩下的公式進行計算。

這里需要注意,BRDF數(shù)值在最后需要進行歸一化處理。

這里給出偽代碼,實現(xiàn)過程非常簡單。

這是沒有進行特殊處理之前的單射線結果

沒有進行特殊處理前的多射線結果

這是進行了特殊處理后的結果,看起來好多了。

作為對比這是直接使用4條射線進行精確反射后的結果,雖然由于更均勻的噪聲分布使得此結果看起來更好一點,但是方差表現(xiàn)是差不多的。

將單射線無特殊處理與單射線+特殊處理的對比,結果確實變得好多了。

這里給出四條射線,每條射線對應四個resolve sample,因此總共就是16個sample的求和積分了,其結果看起來已經(jīng)不錯了,不過這個代價依然有點高昂了。

這里依然使用1條射線四個resolve sample,不過加上了temporal filtering,其結果已經(jīng)可以跟前面給出的四條射線四個resolve sample的結果相媲美了。

對BRDF權重進行重新歸一化還有一個作用,在進行ray tracing的時候,有時候會碰到相鄰像素的ray追蹤不到任何有效物體(即反射方向最終的歸宿是天空),這種情況使得稀疏ray tracing稱為可能。稀疏ray tracing表示,不必為所有的像素都生成其對應的反射射線,而只需要在resolve pass的時候解析出全分辨率的輸出結果即可。(有點繞口,看看后面能不能解惑)

這里給出的前面的輸出結果,是按照half-res trace + half-res resolve的方式實現(xiàn)的。

這里給出的是half-res trace + full-res resolve的輸出結果,因為應用了full-res的temporal filtering,使得噪聲變得更輕微。

先來解釋一下temporal reprojection的含義:給定某個像素的3D世界坐標,通過一定的手段(比如通過velocity buffer)可以得到此像素在上一幀中的世界坐標,并通過計算可以轉換為上一幀中屏幕空間的uv坐標。(拿到有什么用呢,這一幀能夠拿到的顏色數(shù)據(jù)跟上一幀拿到的顏色數(shù)據(jù)應該是一樣的,對于輸出的結果貌似并沒有什么幫助?)

不過,如果上一幀跟當前幀的viewport發(fā)生了變化的時候,就會有點問題,這種時候反射的結果會存在視差(為什么?)。這是因為被反射的物體移動的時候是沿著相機空間對應的深度方向進行的,而非沿著反射平面的深度進行的(每太看懂,意思是深度變化方向),在這種時候,使用最近depth來計算反射的話,得到的結果會對最終color產(chǎn)生污染,寒霜這邊先計算被反射物體的平均深度,之后通過這個深度來進行reproject,這樣得到的結果就好多了。

寒霜使用的Importance sampling跟標準的方法有所不同,想要消除所有的噪點,只能通過大量的采樣,因為其中很大一部分噪點來源于BRDF的尾部數(shù)據(jù),尤其是GGX,因此這里會將生成的采樣點朝著鏡面的方向做一個偏移處理(即將尾部截掉,之后進行歸一化,將能量分配到頭部區(qū)域,相當于將權重更多賦予鏡面反射方向),不過由于在計算中依然希望使用精確的PDF,所以偏移方式比較講究(具體怎么做的?)

這里使用了偽隨機數(shù)作為偏移來生成遠離鏡面方向的偏移量,這種方式可以將截斷的區(qū)域數(shù)據(jù)按比例轉換到非截斷區(qū)域,經(jīng)過這種處理后的PDF跟之前的PDF是一致的,區(qū)別在于乘上了一個常量系數(shù),不過這個常量不需要另行計算,因為前面說過會對BRDF做一次歸一化,這個歸一化操作會將這個常量偏移的影響剔除掉。

另一個減輕方差的方法是對importance sampling進行filtering,前面說過,filtering就是在importance sampling的基礎上,調整最終獲取color時候的算法,根據(jù)表面粗糙度確定reflection cone的張角,之后根據(jù)采樣點的距離確定cone截面的半徑,根據(jù)這個半徑可以計算采樣的mipmap的mip level。

Filtering也可以根據(jù)需要添加bias,從而得到比實際需要的模糊程度更高的模糊結果,這個偏移參數(shù)可以有效的減輕前面說過的importance sampling中的偏移帶來的反射過于尖銳清晰的問題。寒霜的實現(xiàn)中將這兩個bias做了一個綁定,做成了一個bias參數(shù),用于控制實現(xiàn)的過程從完全無偏移的蒙特卡羅算法(得到鏡面反射效果)過渡到提取所有反射方向的輸入得到的超模糊結果。

加大bias將從以下兩個方向提升表現(xiàn):
1.ray-tracing變得更為合乎邏輯(coherent)
2.Mipmap采樣的mip level會更?。ū憩F(xiàn)好在哪里?)

不過過大的偏移也會帶來問題,比如會導致反射顏色不連貫以及漏光等(畢竟屏幕空間位置的臨近并不等同于反射視角上位置也是臨近的),此外還可能不利于實現(xiàn)前面所說的拉長反射效果。

下面看下不同偏移值的效果。

由于temporal filtering的存在,可能不是很能看得出來效果的提升,但是如果將temporal filtering關掉之后,噪點的減少跟性能的提升就很明顯了。

前面說過resolve pass使用的是full-res的RT,在這個過程中會一次性處理四個像素的數(shù)據(jù),并將這個處理結果共享給這四個像素使用,雖然會導致VGPR(每太明白是什么意思,GPU?)負擔加重,但是由于對于這四個像素來說,只需要執(zhí)行一次data fetch操作,從而節(jié)省了帶寬,還是很劃算的。此外,由于前面假設這四個點的反射射線的交點都是相同的,因此在屏幕空間的depth buffer的相交檢測也只需要執(zhí)行一次。

不過這里需要注意,對于這四個像素而言,在從mipmap貼圖中讀取對應的color數(shù)據(jù)的時候,其使用的mip level卻不一定是相同的,因為四個像素的粗糙度可能都是不一樣的,這里寒霜使用了一種跟DXT貼圖壓縮實現(xiàn)算法相類似的trick來解決這里的不一致問題,先計算出四個像素的min/max mip level,之后在使用的時候,只需要fetch min & max mip level的color數(shù)據(jù),并根據(jù)roughness進行插值即可,這樣就將貼圖采樣數(shù)目從四個降低到了兩個。

這里給出了這種算法的實現(xiàn)效果比對,相對于單個mip fetch,這種算法與4 mip fetch的區(qū)別已經(jīng)非常小了。

SSR(SSGI)有其固有缺陷,比如上圖中顯示的,不在屏幕內的數(shù)據(jù),其反射結果就拿不到,從而導致效果的異常。

不過基于其本身的眾多優(yōu)點,并不不妨礙這個算法的使用:

  1. 因為Hi-Z(HZB)的精度非常高,在兩個物體的交接面處的非常細膩的幾個 pixel 的內容誤差,都能被計算出來,因此可以用來模擬非常近的Contact Shadow,這個功能在基于Voxel的算法中要想做到會比較困難
  2. 因為基于Hi-Z 的方法獲取到的碰撞點會非常準確,因此其計算精度會比基于voxel的GI算法要強很多
  3. 計算復雜度只跟屏幕分辨率有關,跟場景復雜度無關
  4. SSGI能夠處理動態(tài)的物體

基于上述優(yōu)點,UE的Lumen也借鑒了其中的一部分思想。

給出了PS4上面的性能消耗。

參考

[1]. Dynamic Global Illumination and Lumen

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容