【技術美術百人計劃】SSAO屏幕空間環(huán)境光遮蔽
一、SSAO介紹
AO
環(huán)境光遮蔽,全稱Ambient Occlusion,是計算機圖形學中一種著色和渲染技術,模擬光線達到物體的能力的粗略的全局方法,描述光線到達物體表面的能力。
SSAO
屏幕空間環(huán)境光遮蔽,全稱Screen Space Ambient Occlusion,一種用于計算機圖形中實時實現(xiàn)近似環(huán)境光遮蔽效果的渲染技術。它不是場景的預處理,而是一種屏幕后處理技術,通過在屏幕像素的位置布置隨機個采樣點,然后通過采樣點遮蔽項所占的百分比來計算陰影遮蔽強度。
SSAO歷史
AO這項技術最早實在Siggraph 2002年會上由ILM(工業(yè)光魔)的技術主管Hayden Landis所展示,當時就被叫做Ambient Occlusion。
2007年,Crytek公司發(fā)布了一款叫做屏幕空間環(huán)境光遮蔽的技術,并用在了他們的看家作孤島危機上。
二、SSAO原理

獲取深度、法線緩沖
基于深度計算像素坐標、基于法線計算法向半球隨機向量
計算像素隨機后的坐標
獲取隨機后的深度并比較
判斷加權AO
后處理
公式:
代表
的法線,
代表點
切平面正方向的任意單位向量,
是可見函數(shù),如果點
在
方向被遮擋則為1,否則為0。
由此可見, 計算AO系數(shù)是一個頗為昂貴的操作. 一般離線渲染器都會采用Ray-Tracing(光線追蹤)或是簡化的Ray-Marching(所謂光線行進)算法, 模擬若干條射線以計算遮蔽百分比. 很明顯這種方式不可能應用到實時圖形渲染中. 盡管目前有一些實時計算AO的新技術, 但是其性能距離普及還有很長的路要走.

上圖為基于Ray-Tracing的AO計算模型. 紅色的射線表示V = 1, 綠色的射線表示V = 0.
那么我們能否Trade Off, 用差一點的渲染結果來獲得更高的運行效率呢? 答案是肯定的, 而且方法還遠不止一種. 本文將重點放在SSAO上.
顧名思義, "Screen Space"意味著SSAO并不是場景的預處理, 而是屏幕后期處理. 其原理是在片元著色器中對于屏幕上的每個像素模擬若干個位置隨機的采樣點, 用被遮蔽的采樣點數(shù)量百分比來近似表示光照強度系數(shù).
黑色為需要計算的樣本、藍色表示樣本法向量
白色、灰色為采樣點,灰色表示被遮擋的采樣點,據(jù)此判斷AO強度
圖2為法向球形采樣該采樣方式會導致平面也會產(chǎn)生AO效果。

參考:游戲后期特效第四發(fā) -- 屏幕空間環(huán)境光遮蔽(SSAO) - 知乎 (zhihu.com)
????????????https://zhuanlan.zhihu.com/p/25038820
三、SSAO算法實現(xiàn)


NDC空間
很多人初次學習把剪裁空間(Clip Space)和標準化設備坐標(NDC)混淆成同一個東西,事實上它們是完全不同的。
Clip Space是一個頂點乘以MVP矩陣之后所在的空間,Vertex Shader的輸出就是在Clip Space上(劃重點),接著由GPU自己做透視除法將頂點轉(zhuǎn)到NDC。
透視除法將Clip Space頂點的4個分量都除以w分量,就從Clip Space轉(zhuǎn)換到了NDC了。
而NDC是一個長寬高取值范圍為[-1,1]的立方體,超過這個范圍的頂點,會被GPU剪裁。

注:在DirectX里面,NDC的z方向取值范圍是[0,1],在Unity中可以用UNITY_NEAR_CLIP_VALUE
獲取z方向近平面的值,在openGL環(huán)境下是-1.0,DirectX中是0.0。

最后通過從相機經(jīng)過對應像素到遠平面的射線乘以線性深度值得到最后的像素坐標。
構建法向量的正交基

切線的計算原理:
因為法線已經(jīng)確定,所以需要從切平面中隨機計算出一條切線。
先隨機一個法向半球的向量r。在求得r在法向法向上的投影a,然后再通過r-a得到切線。
AO采樣核心

_SampleKernelArray[i]是在c#計算的采樣點的隨機位置偏移量,先把這個偏移量從切線空間轉(zhuǎn)到觀察空間,然后把得到的加上像素點坐標得到對應的采樣點坐標。然后再把采樣點從觀察空間轉(zhuǎn)到屏幕空間,用得到的屏幕坐標采樣深度緩沖獲取采樣點的深度值randomDepth,然后拿這個randomDepth跟linear01Depth來進行比較,如果randomDepth>linear01Depth,那么進行AO加權。
四、SSAO算法改進
隨機正交基

因為之前的構建TBN矩陣中的隨機向量是固定的,所以為了讓TBN矩陣具有隨機性,那么需要把隨機的向量存入紋理中(需要設置為repeat模式),然后根據(jù)平鋪來進行隨機采樣,這樣就能得到隨機的向量,進而構建隨機的TBN矩陣。
AO累加平滑優(yōu)化

_RangeStrength是設置的閾值,如果randomDepth和linearDepth的差值的絕對值大于我們設定的閾值,那么很有可能是非常遠(比如天空),那么就不需要進行AO加權。

同樣的,如果隨機點深度值跟自身非常近,那么可能會導致明明再同一平面,但是也會出現(xiàn)AO加權,這個時候設置一個非常小的偏移值來比較判斷。只有當前像素深度小于隨機點像素深度才能夠貢獻AO。

對于權重部分,是隨機向量跟半球法線向量相似度越高,所占的權重越小,反之所占權重就為1。應該是跟法線相近的向量一般大概率是沒有被遮蔽,沒有太大的參考性,所以所占的權重才會小吧。
對于循環(huán)內(nèi)AO的貢獻公式為:
ao+=range*selfCheck*weight;
AO模糊

跟高斯模糊有些相似,也是通過兩個一維卷積核進行卷積運算的,但是不同的是,通過中間像素兩邊像素的法線的點乘再加上設置的閾值來除去特定頻域的信息。

nor1和nor2分別是兩邊的法線,如果法線之間的夾角過大導致點乘小于設定的閾值_BilaterFilterFactor,那么這次運算的權重為0。
參考:UnityShader-BilateralFilter(雙邊濾波,磨皮濾鏡)_puppet_master的專欄-CSDN博客
????????????https://blog.csdn.net/puppet_master/article/details/83066572
五、對比模型烘焙AO
烘焙方式
三維建模軟件烘焙AO方式
通過三維建模軟件(如3DMax),設定好渲染參數(shù),對模型(單一選擇模型實體),烘焙AO到紋理。
游戲引擎烘焙AO方式(Unity3D Lighting)
通過Unity的Lighting功能(主菜單/Window/Rendering/Lighting Setting)進行場景的烘焙,AO信息包含于此。
建模軟件烘焙優(yōu)缺點
優(yōu)點:
單一物體可控性強(通過單一物體的材質(zhì)球上的AO紋理貼圖),可以控制單一物體的AO的強弱;
彌補場景烘焙的細節(jié),整體場景的烘焙(包含AO信息),并不能完全包含單一物體細節(jié)上的AO,而通過三維建模軟件烘焙到紋理的方式,增加物體的AO細節(jié)。
不影響其(Unity場景中)靜態(tài)或者動態(tài)。
缺點:
操作較其它方式繁瑣,需要對模型進行UW處理,再進行烘焙到紋理。
不利于整體場景的整合(如3DMax烘焙到紋理,只能選擇單一物體,針對整體場景的處理工作量巨大);
增加AO紋理貼圖,不利于資源優(yōu)化(后期可通過其它紋理通道整合資源);
只有物體本身具有AO信息,獲取物體之間的AO信息工作量巨大。
Unity烘焙優(yōu)缺點
優(yōu)點:
操作簡易,整體場景的烘焙,包含AO的選擇。
不受物體本身的UW影響,Unity通過Generate Lightmap UVs生成模型第二個紋理坐標數(shù)據(jù)。
可以生成物體與物體之間的AO信息。
缺點:
缺少單一物體的細節(jié)(可調(diào)整參數(shù)提高烘焙細節(jié),但換之將增加烘焙紋理數(shù)量和尺寸,以及烘焙時間);
受物體是否靜態(tài)影響,動態(tài)物體無法進行烘焙而獲得AO信息。
SSAO優(yōu)缺點
優(yōu)點:
不依賴場景的復雜度,其效果質(zhì)量依賴于最終圖片像素大小。
實時計算,可用于動態(tài)場景。
可控性強,靈活性強,操作簡單。
缺點:
性能消耗較之上述2種方式更多,計算非常昂貴。
AO質(zhì)量上要比離線渲染烘焙(上述2種)不佳(理論上)。
六、SSAO性能消耗
性能消耗的主要方面

AO核心采樣消耗說明

使用For循環(huán)進行半球隨機向量的采用,IF、For等對于GPU計算性能上并不友好。
采用數(shù)的數(shù)量(上圖中的_SampleKernelCount,針對For循環(huán)的次數(shù)),過低的采用數(shù)得不到好的結果;以64為例,1334x750的分辨率,每個像素計算循環(huán)64次,合計1334*750*64次AO核心運算;
循環(huán)體內(nèi)部的采樣邏輯,每個像素中的迭代需要采樣64次的屏幕深度值法線值。
濾波采樣消耗說明
本案例采樣的是雙邊濾波(Bilateral Filter),為了保證邊緣不被模糊,采樣基于法線的雙邊濾波。

c#后期腳本中,Bilt兩次(橫向和縱向),合計調(diào)用兩次濾波渲染Pass;
單一濾波渲染Pass中,多重采樣;包括7次主紋理的采用和7次屏幕的法線信息的采用,屏幕中每個像素合計14次紋理采用。
七、拓展鏈接
【環(huán)境遮罩原理】環(huán)境遮罩之SSAO原理 - 知乎 (zhihu.com)
https://zhuanlan.zhihu.com/p/46633896
【游戲后期特效第四發(fā)--屏幕空間環(huán)境光遮蔽 (SSAO)】游戲后期特效第四發(fā) -- 屏幕空間環(huán)境光遮蔽(SSAO) - 知乎 (zhihu.com)
https://zhuanlan.zhihu.com/p/25038820
【屏幕空間環(huán)境光遮蔽(SSAO)算法的實現(xiàn)】屏幕空間環(huán)境光遮蔽(SSAO)算法的實現(xiàn)_小龍蝦的博客-CSDN博客_環(huán)境光遮蔽
https://blog.csdn.net/qq_39300235/article/details/102460405
【SSAO 與深度重構】第四十六課 SSAO 與深度重構 - 現(xiàn)代 OpenGL 教程(連載) - 極客學院Wiki (jikexueyuan.com)
【Ambient Occlusion(AO)使用指南】Ambient Occlusion(AO)使用指南 - 知乎 (zhihu.com)
https://zhuanlan.zhihu.com/p/150431414
【圖形和濾波】圖像與濾波 - 阮一峰的網(wǎng)絡日志 (ruanyifeng.com)
https://www.ruanyifeng.com/blog/2017/12/image-and-wave-filters.html
【雙邊濾波】UnityShader-BilateralFilter(雙邊濾波,磨皮濾鏡)_puppet_master的專欄-CSDN博客
https://blog.csdn.net/puppet_master/article/details/83066572
【技術美術百人計劃】SSAO屏幕空間環(huán)境光遮蔽的評論 (共 條)
