基於GPU的快速烘焙AO貼圖

基於GPU的快速烘焙AO貼圖

來自專欄 MACK的遊戲開發筆記

這是之前專利文檔的詳細介紹。在12年的時候為了進一步提升遊戲品質增加場景的立體感,美術希望引入AO效果。因為自研場景編輯器本身就包含了烘焙Lightmap和Shadowmap的功能,速度也非常快,因此我們希望進一步擴展增加烘焙AO的流程。

首先我們嘗試集成了Beast來進行烘焙,但是集成之後烘焙一張場景需要二十幾個小時的時間,即使只烘焙AO速度也非常慢需要接近一小時(當時Beast並不支持聯合烘焙)。因為遊戲有上百張地圖,美術同學的期望是所見即所得,能在幾分鐘內看到效果並且可以實時調整AO貼圖的濃度效果,因此還是決定使用自研的烘焙方式並在增加一種自研的快速烘焙AO的功能。

首先我們嘗試了在CPU中通過發射射線的方式計算AO,效率也是極低。然後又嘗試了利用GPU,使用SSAO的方式烘焙靜態AO,實現後發現速度還可以但是精度效果無法滿足。

最終我們自己想了一種使用陰影演算法來烘焙AO的近似演算法。大致流程就是對烘焙物體產生一組球形分布的射線,每個射線單獨對物體進行陰影的烘焙(使用遊戲內實時陰影的演算法,非常快),然後將各個陰影貼圖進行權重疊加得到一張混合陰影圖模擬AO效果,而這個任務也落到了我身上。比較有意思的是這個方式當時並不是參考其他論文方案實現的,而是自己嘗試發現的。但是在實現做過分享之後,過了兩個月其他公司就拿相似的文檔去申請專利,連一些描述參數都是一模一樣的…..實在很難說是巧合,好在最後還是成功申請了專利否則真的是尷尬了。

什麼是AO

AO,Ambient Occlusion,一般稱作「環境光遮蔽」。百度百科的描述,AO是來描繪物體和物體相交或靠近的時候遮擋周圍漫反射光線的效果,可以解決或改善漏光、飄和陰影不實等問題,解決或改善場景中縫隙、褶皺與牆角、角線以及細小物體等的表現不清晰問題,綜合改善細節尤其是暗部陰影,增強空間的層次感、真實感,同時加強和改善畫面明暗對比,增強畫面的藝術性。

簡單來說就是通過簡化演算法模擬全局光中的部分光照,可以提升場景的立體感,縱深感,看上去更真實。

下圖就是不使用AO,單獨顯示AO,最終效果的三張截圖:

演算法原理:

常規的AO是通過每個點向周圍(全球或半球)發射n條射線,判斷點到交點的距離作為權重並累加作為AO值。而我們的做法是對每個物件生成一組球形分布的射線,可以理解為球形光源,每個光源產生一個陰影值,這個陰影值就作為這個點是否被遮擋的結果,然後疊加各個方向的結果產生出一張近似的AO貼圖。因為採用的是實時陰影的演算法,整個計算非常快,只要幾百ms即可得到結果。

計算流程:

實現細節:

  • 生成球形射線。依據球諧光照中生成均勻分布的球形射線的方法,生成900個(實際測試得到的性價比最高的值)射線。首先為了批量烘焙,針對每個可能的解析度創建AOMap的RT,為了保證精度採用FLOAT_COLOR_128
  • 渲染深度圖。遍歷每條射線進行烘焙,傳入模型根節點,包圍盒,貼圖,寬度,權重(即光源數分之一),射線方向。依據方向和固定位置計算出攝像機的位置,得到深度相機,設置View矩陣,設置視口。為了保證物體所有點的AO攝像方向一致,需要依據物體的包圍盒生成平行投影矩陣,將物件包圍盒轉到View空間計算。在VS里輸出屏幕坐標和UV,在PS里將屏幕坐標歸一化,通過Pack壓縮得到深度圖,需要採用基礎貼圖得到Alpha
  • 計算AO。遍歷每條射線,設置垂直向下的平行投影攝像機,六面體正好照到物件。設置深度貼圖,設置RT(第一次需要ClearAll),設置Camera和Shader進行烘焙。VS里直接將UV轉換成投影坐標,-1到1(其實就是去渲染UV貼圖上像素對應的3D點),輸出世界坐標和世界法線。在PS中,計算光的方向和該點的法線的點積作為權重之一,計算出點光的投影空間的坐標,歸一化得到-1到1,然後再轉換成0到1,注意y需要取反用1減(貼圖坐標方向和坐標軸方向的不同的原因)最後得到該點在貼圖上的坐標,然後解壓深度貼圖,求的該點光空間的深度與自己的深度相比,如果光空間的深度值大說明該點被遮擋中,AO值為1,再乘以方向的權重,光數目的權重,係數,最後輸入到rg通道中,ba通道設置為1作為mask
  • 修正。因為像素溢出的問題,得到的AO貼圖會有黑邊。因此還需要進行修正,修正方法就是將AO貼圖再渲染到一個相同的大小的RT中,在PS中通過Mask進行區分,有效像素直接寫陰影值,無效像素則採用周圍8個像素,得到有效像素取平均值,相當於擴充了一個像素。

工作流集成和優化:

完成了AO的演算法只是萬里長征走完了第一步,而真正要投入使用,做到產品化還要需要做大量的後期工作,所消耗的時間遠超AO演算法本身的時間。

  • 在編輯器中加入批量烘焙AO,單獨對某個地形,某個物體,以及某些選中物體的功能,美術同學既可以對整張地圖進行一次性烘焙,也可以針對修改過的物件進行單個烘焙

    加入了對半透明物件烘焙AO的功能,需要計算半透明度

  • 加入了烘焙AO的進度預測,時間統計信息等功能,便於測試性能和給美術同學一個精準的預期
  • 在編輯器和客戶端中增加了AO快關,只顯示AO等調試功能,便於對比效果和檢查錯誤
  • 烘焙出來的AO效果可能並不滿足美術同學對場景風格的預期,因此又增加了Gamma矯正,純黑指定,整體加亮加暗,顏色過濾等功能,並提供了相應的數值和曲線編輯面板。美術可以實時修改AO貼圖的顏色曲線,調整到一個比較滿意的後期處理效果
  • AO貼圖解析度優化,實際使用過程中會發現,如果貼圖的解析度太小UV不合理就會出現採用錯誤,如果解析度太高又會佔用大量的硬碟和內存空間,因此又加入了依據物件的包圍盒,場景大小,人工係數自動計算AO貼圖大小的演算法,同時也允許美術單獨或批量指定AO貼圖的解析度
  • 實際測試中發現對於大場景烘焙物件的速度會呈指數下降,主要瓶頸在裁剪上,因此又引入了四叉樹來快速剔除,對地形的AO貼圖不進行過濾去黑邊的操作等優化方式,大幅提升烘焙速度
  • 實際使用中發現烘焙速度很快,但是從編輯器導出AO貼圖到地圖數據的過程非常慢,測試發現是因為dds壓縮的功能呢,因此使用了nvidia的新的dds壓縮庫nvtt,並使用了cuda加速。但發布版本給美術使用之後發現優化過的編輯器導出的AO貼圖經常會出現詭異的錯亂問題。最後確認是Cuda加速的bug,如果美術使用的顯卡不是Nvidia的圖形顯卡(ATI的顯卡和Nvidia的民用顯卡都有概率會出問題),或者在烘焙的過程中鎖屏了就會出現錯亂,最終放棄了Cuda加速
  • 實際使用中發現客戶端的AO效果會有白斑問題,又修改了烘焙AOShader的貼圖採用方式,消除了白斑
  • 還加入了生成AO時進行高斯模糊過濾,可以得到更加平滑的AO貼圖
  • 為了降低客戶端容量,我將Ligmap分成兩張,一張貼圖的G通道存AO,R通道存陰影,另一張的存點光的光照和陰影,兩張貼圖都使用Dxt1的壓縮方式,極大的節省了安裝包和內存的大小。

最終效果:

最終完成了GPU烘焙AO的功能,並集成到了美術的工作流中。同一張地圖使用Beast烘焙AO需要45分鐘,而使用自己開發烘焙方式只需要2分鐘,單個物件不到1秒,極大的提升了美術同學的開發效率。


推薦閱讀:

還原漢晉士族的抉擇與生態:獨家專訪《三國志姜維傳》作者Ratchet(上)
《我的世界挖礦》等級有什麼用?
如何評價尼爾機械紀元這部遊戲?
4399小遊戲為什麼被起訴?
遊戲的未來:神經遊戲時代

TAG:渲染 | 計算機圖形學 | 遊戲 |