GDC粗讀|看看《暗區突圍》手機版如何做光線追蹤


3樓貓 發佈時間:2024-06-28 11:32:37 作者:Hakumen Language

前言

這周由於玩《艾爾登法環》的原因,讀一篇略短一些的GDC文章的內容,分享人是騰訊的《暗區突圍》(英文名:
Arena Breakout)項目的渲染主程Junhong Wang
我個人認為國內手機跨平臺遊戲中,在世界規模、美術視覺和性能幾個方面綜合來說都還不錯的有米哈遊的《原神》,騰訊的幾個槍戰遊戲,網易的《明日之後》等——這幾個也是GDC上都發過分享的國內產品。今年也持續會出很多類似規模的遊戲,但具體表現還需要觀察。
另外,我個人覺得騰訊遊戲其實不是以技術規模製勝的,它更多是一個商業成功的發行商和養蠱者;但反過來說,其實騰訊內部也是有很多技術大神的,我也樂見他們能拿出這種有技術含量的又能商業成功的產品。當然我個人有一套評價標準,肯定不是說商業成功就是一切——讀技術分享的文章裡我就不對模仿原罪問題和大公司團隊內耗問題表達個人觀點了。
本次內容還是以配圖並翻譯原文為主,同時打星號的部分是我個人的一些備註與分析。

一、項目背景概述

*整個項目是搭建在虛幻4引擎上的開放世界大地圖FPS遊戲,對於安卓和IOS有不同的圖形API。
關於《暗區突圍》手機版

關於《暗區突圍》手機版

  • 前向渲染管線
  • 基於物理的渲染
  • 動態天氣系統(Chan22 可以參考文末列出的另一篇分享)
  • 室內場景的全局光照是基於預計算的
——手機光線追蹤
  • 最新的智能手機已經具備了硬件加速的射線查詢(Ray Query)功能
  • 射線查詢可以在Shader的任何層級使用(指預計算、頂點、片元等)
  • 大部分幀捕獲(Frame Capture)分析工具不支持手機Vulkan射線查詢
——啟用光追的準備
  • 開啟Vulkan在安卓上的圖形API(RHI是Render Hardware Interface的縮寫)
  • 更新Shader的交叉編譯(ShaderConductor是UE的一個功能)
  • 拓展UE4中的Vulkan和Metal的RHI
《暗區突圍》手機版中的光追應用

《暗區突圍》手機版中的光追應用

*安卓版光追已經發布了,IOS版(截至分享日)還在開發中。
*光追主要應用到反射、軟陰影、AO這幾方面。

二、光線追蹤的場景管理

*雖然基礎思想都是射線可以進行遞歸的彈射查詢,但手機端主要考慮的是減少檢測數量和優化加速結構。
挑戰——圖中展示了PC上通過Nisight捕獲調試的TLAS

挑戰——圖中展示了PC上通過Nisight捕獲調試的TLAS

  • 底層加速結構(BLAS)的內存使用
  • 構架BLAS是很昂貴的
  • 在有過多實例時,最終上層加速結構(TLAS)也很昂貴
* Bottom-Level-Acceleration-Structure(BLAS)定義了幾何體的基本組成。如果物體是網格形式就是三角面的頂點索引,也支持其他組織形式比如體素,曲線等,但要自行構建加速方式。Top-Level-Acceleration-Structure(TLAS)定義了場景實例層的相關屬性例如包圍盒、變換矩陣等數據 。簡單來說可以參照下圖:
Nvidia 的practical-real-time-ray-tracing-rtx中的配圖

Nvidia 的practical-real-time-ray-tracing-rtx中的配圖

——世界總覽
  • 關卡通過關卡streaming系統管理
  • 低LOD精度的網格在package加載時一起加載
  • 高精度LOD通過網格streaming系統動態加載
  • 包含遮罩、世界座標偏移、透明材質的網格不創建BLAS
——在LOD加載時創建BLAS?
  • 需要加載超過4700個BLAS
  • 內存佔用過大導致崩潰
構建和銷燬BLAS

構建和銷燬BLAS

  • P是攝像機位置
  • r1是BLAS創建的半徑
  • r2是BLAS銷燬的半徑
  • d是攝像機距離物體包圍盒的距離
構建和銷燬BLAS

構建和銷燬BLAS

  • 當物體在r1範圍時進行鬆散的BLAS加載(lazy 這裡指響應不用那麼及時的)
  • 在n幀後在進行BLAS的延時銷燬以避免頻繁創建和銷燬
  • 所有參數都是可以縮放改變的
——結果:
*加載數和內存用量降到了700個BLAS和1.1G
頂層加速結構TLAS

頂層加速結構TLAS

  • 每幀更新
  • 需要對實例進行剔除(引用的2個剔除算法改進可以參考文末資料名稱)
在VIVO X90上的性能情況

在VIVO X90上的性能情況

三、光線追蹤的反射

反射關閉時

反射關閉時

反射開啟時

反射開啟時

*由於射線數量限制,這裡的反射只能是鏡面反射,沒辦法做出鏡面和漫反射之間的粗糙度效果。因此粗糙度只能通過模糊處理等方式來近似,後面會提到。
光追反射的挑戰

光追反射的挑戰

——反射像素的著色
  • 沒有RTPSO(DX12中自帶的一套可編程的光追次級結構)
  • 沒有無綁定紋理(ShaderModel 5.1中提出的一套更靈活的紋理尋址方式,可以優化GPU調用及顯存)
  • 上千種不同材質
——混合的渲染管線
  • 當前的主渲染管線是前向渲染(引入光追後需要引入一些類似延遲渲染的幀緩衝)
——性能:能耗、幀率
反射管線分析:
基礎pass(不透明場景顏色、法線粗糙度和檢測標誌、深度)——場景查詢pass——可見性處理pass——聯合雙邊濾波過濾——聯合雙邊濾波過濾(參數不同)——混合——後處理
*後面逐步介紹了各步驟的一些細節。
(數據)準備

(數據)準備

  • 創建用於射線反射查詢的特殊網格shader
  • 收集射線查詢網格的渲染指令
  • 每幀重新為網格繪製指令分配網格實例ID
  • 當構建TLAS時,指派網格實例ID和HitGroupId
基礎pass

基礎pass

——MRT(這裡是MultiRenderTarget,繪製到多個幀緩衝。相應的RT就是渲染目標紋理)
  • RT0:場景顏色(R11G11B10 數字是顏色位數)
  • RT1:定製化的GBuffer(法線+粗糙度+標誌位 A2B10G10R10 參考延遲渲染管線
——深度模板:D24S8
——可選:(對於金屬材質)反射顏色
屏幕空間場景查詢pass

屏幕空間場景查詢pass

  • RT0:壓縮編碼後的三角面ID和射線命中的重心座標
  • 可選RT:射線命中的方向
  • 深度緩衝:射線命中的紋理繪製ID
  • 算法:
  1. 重新構建攝像機相關的世界空間座標和反射線方向
  2. 射出射線,如果命中TLAS實例,獲得其網格實例ID、三角面ID和命中點的重心座標
  3. 輸出結果至RT0和深度緩衝
*關於重心座標在Games101中有詳細介紹,主要是通過和三角形頂點的關係來定義三角面中的任意點。
——可見性處理pass(CPU)
  • 發出射線查詢可見性處理的渲染指令——繪製ID通過統一的緩衝區提交
  • 每一個繪製指令覆蓋全屏四邊形範圍
——可見性處理pass(GPU)
  • 如果繪製ID不匹配(檢測不通過),則丟棄該像素
  • 在像素(片元)著色器中進行PBR參數的插值
  • 發出陰影查詢射線(*與深度緩衝比較)
  • 計算直接光照和間接光照
  • 寫入反射RT
優點:較好的硬件兼容性
缺點:
  • 繪製指令數量和TLAS數量一致(600多個)
  • 重疊繪製——太多全屏四邊形繪製
與之前相比的優化方案

與之前相比的優化方案

——繪製指令:使用GPU剔除查詢來去除不可見的網格繪製指令
——重疊繪製:
  • 在頂點shader中,為網格繪製ID分配四邊形深度
  • 開啟深度檢測以避免重疊繪製
*優化後減少到了110個draw call,且沒有重疊繪製了。
模糊pass1

模糊pass1

輸入紋理:反射貼圖、定製化的GBuffer貼圖、深度貼圖
算法: 聯合雙邊濾波,模糊核偏移尺寸基於粗糙度調整
*關於模糊算法和核(Kernel)之前我有一篇文章介紹過。關於聯合雙邊濾波,簡單來說是一種可以較好保持原圖邊緣的模糊和降噪算法,文末會附加資料鏈接。
模糊pass2

模糊pass2

*通過聯合雙邊濾波再算一遍,但模糊核偏移更大了。
混合pass

混合pass

  1. 邊緣保持
  2. 對於光滑地板有銳利的反射結果
  3. 對於粗糙牆壁有模糊的反射結果
  4. 對完全粗糙的材質不發出射線
*這裡的模糊反射效果是基於單一射線查詢加模糊算法得出的,而複雜的光線傳播是會有多條光線散射並求積的情況的。離線渲染中會對粗糙度不同表面採用蒙特卡洛積分(採樣)的方式來求積。所以從這個意義上說這裡算反射還是用的前現代的光追算法,和1974年的Witted Style一致。
優點:較好的硬件適配,高性能
缺點:難以處理半透明或有遮罩的材質

四、光線追蹤的AO和軟陰影

關閉光追AO

關閉光追AO

開啟光錐AO

開啟光錐AO

基於多層陰影紋理的陰影(Cascade Shadow Map)

基於多層陰影紋理的陰影(Cascade Shadow Map)

光追開啟時的陰影和AO

光追開啟時的陰影和AO

*可以看到開啟光追後,陰影和AO質量都有較大提升。
陰影和AO做光追的挑戰

陰影和AO做光追的挑戰

兩者都需要大量射線:陰影1根、AO1根、沒有降噪輔助。
需要考慮性能表現。

軟陰影和AO的光追管線分析:
前置pass——場景查詢pass——分幀降噪——A-Trous過濾(2個pass)——基礎pass——後處理pass
*前置pass包含了場景的法線和深度,後面從場景查詢pass開始介紹。
  • 把太陽當作一個圓球(普通光源可能抽象成一個點,但光追很難追蹤一個點)
  • 採用深度來重新構建射線原點,使用Halton序列來生成採樣方向
  • (每幀)陰影1根射線,AO1根射線
  • (幀緩衝的)R通道用於陰影、G通道用於AO
  • 陰影射線背面剔除
  • 以較低分辨率執行
*這裡其實就類似現代光追面臨的問題了,在每個採樣點需要更多信息來確認陰影和AO情況,但性能上只允許每個點一幀採樣一根射線。可以看到只運行一幀時偏差很大,所以Games202的閆老師說過目前實時光追的核心技術是降噪,這既有調侃的意味,很大程度上也是事實。
分幀降噪pass

分幀降噪pass

  • 對屏幕位置與前一幀的陰影和AO紋理(中的點)做重映射之後的比較
  • 基於深度比較做排除(例如前一幀未被遮擋,後一幀被擋住的情況)
*Temporal——基於時間的。如果瞭解過TAA應該不難理解。
A-Trous過濾pass(2次)

A-Trous過濾pass(2次)

*A-Trous算法也被翻譯為多孔算法。簡單來說它比聯合雙邊濾波有更好的性能,但單次運算效果相對較差,需要多幀平攤來得到還不錯的結果——且兩者都有著不錯的邊緣保持特性。
*關於分幀降噪在Games202的實時光線追蹤一節中有詳細介紹,這兩種降噪算法都涉及到了。
*通過加倍太陽的尺寸,得到了更柔和的陰影。(以及展示整體的陰影和AO結果)
與場景混合後的結果

與場景混合後的結果

一些缺點:
  • 一些有遮罩的網格(例如樹葉)必須使用其它的陰影算法
  • 有透明材質的網格無法採樣出正確的陰影和AO值(必須為此發射新的射線)
  • 太多渲染pass和紋理採樣導致較高的能耗

結語

總的來說,手機版的光線追蹤還處於秀肌肉大於實用的階段,畢竟玩手機其實畫質比起幀數或能耗來說反而不那麼重要。作為我個人來說,手機遊戲都是看看高畫質然後開省電玩的,畢竟手機也不是隻打遊戲的。
但我確實理解為什麼他們要儘早在手機上做光追(雖然性價比高的還是前現代光追算法做的反射,而現代光追算法做的陰影和AO手機上有點太耗了),這不僅僅是一個噱頭:一方面來說,這套兼容傳統管線和簡單光追的管線既然適配了手機端,那麼完全可以以更高質量應用於全平臺(實際上這遊戲也有PC端);另一方面,這對於開發人員本身也是寶貴的技術積累,畢竟國內做帶有光追的大型3A項目的機會更少,也更難深度定製與優化渲染管線——能在保證項目質量的基礎上開展技術升級也是很難得的(反面則是不斷練手但是項目爛尾了)。
實際上這個遊戲中他們沒有發明全新的定製化光追方案,而是一事一議的在UE4的管線、Vulkan新版本API的框架內做了很多優化——與其說他們是“做”光追,不如說是優化光追。很多優化成果也是對前人成果的一些迭代和演進。
圖中是一些關聯的分享或論文內容

圖中是一些關聯的分享或論文內容

很多時候做手機遊戲進行技術突破,就面臨一個“為什麼要做”的靈魂問題——畢竟常有一類說法是“某某遊戲畫面那麼稀爛反而買量容易、更好賺錢”;但真等到《原神》這類項目憋大招出來靠管線技術突破和規模效應獲得了商業成功,再要從頭追趕又傻眼了。從我個人的觀察來看,騰訊魔方工作室在3D項目的技術積累上確實略好於天美工作室群,可能是因為天美本身有太多躺著賺錢的產品了。
這裡還是要復讀我的一個觀點——3D手機遊戲的技術積累不是僅僅積累給手機端的,尤其是對於商業(通用)引擎的技術積累上,這對於整個國內遊戲行業都是普適的。

最後是資料鏈接:
《Ray Tracing in Arena Breakout Mobile》 這篇分享的GDC地址
Games202官方主頁
Nvidia的Practical Real-Time Ray Tracing With RTX
一篇寫得很好的介紹Unreal引擎光追的知乎文章



© 2022 3樓貓 下載APP 站點地圖 廣告合作:asmrly666@gmail.com