游戏中的实时光线追踪技术与技巧
提到游戲使用的實時渲染,很多人都會覺得光柵化渲染是唯一的方法,而想要在游戲中使用實時的光線追蹤,似乎還是遙遠的夢想。
雖然整體的光線追蹤實時渲染架構以及相關硬件還在試驗階段,但從2016GDC的技術展示來看,游戲開發者在實踐中已經找到了不少能利用現有架構實現光線追蹤的小技巧,光線追蹤技術已經悄悄地開始在游戲開發中發揮作用了。
光線追蹤的優點自不用說,容易理解、實現簡單、支持體積渲染,況且還有shadertoy上那么多使用光線追蹤制作的眩目效果。但問題是光線追蹤和現有的游戲引擎架構不統一,而且實時運行的效率不高,如果要做體積渲染還存在如何存儲和采樣體積數據的問題。
下面的內容會介紹一些在現有游戲引擎里針對這些問題解決方案。
減少計算量
首先光線追蹤在實時運行時最大的問題是對PixelShader的壓力太大,shadertoy中很多代碼都在PixelShader中循環幾十上百次,顯然在真實開發中很難使用這樣的代碼。
這里介紹一種使用VertexShader進行光線追蹤的思路,以制作實時溶球作為例子。
直接實現的思路是建立溶球的Distance Field,在PixelShader中從視點開始推進光線,循環直到Distance Field為0,達到溶球表面,然后計算反射折射等。這樣的方法,在PixelShader中至少需要十幾次循環才能trace到溶球表面。
?
改進思路是將光線追蹤代碼移到VertexShader中,在Mesh的每個頂點進行光線追蹤計算,按照光線追蹤的結果進行頂點變形。如圖中,使用一個球形的Mesh做頂點變形,每個頂點的位置按照光線追蹤的結果向內收縮,直到溶球表面。
?
如果選擇合適的球形Mesh大小和位置,收縮的步驟可以小到三次以內。這個方法同時減少了光線追蹤的循環次數,也減輕了PixelShader的壓力。完全可以在移動平臺上運行。
?
另一種減少計算量的方法就是Dithering,在獨立游戲Inside中的體積光渲染就使用了這種的技術。
在我的另外一篇游戲開發相關實時渲染技術之體積光描述過高質量的體積光渲染應該使用光線追蹤的方法。問題在于優質的體積渲染需要的循環次數可能會達到一百次以上,如果循環次數降低到一定程度會因為采樣數不足,會造成條紋狀瑕疵。
這里的改進思路是,在光線追蹤的起點添加隨機噪音,這樣QQ靚號轉讓平臺條紋狀瑕疵會變成更加隨機的噪點。之后再添加一層模糊或者是抗鋸齒,這樣整體的瑕疵感就會明顯減少。
這種方法的缺點就是渲染的對象會顯得比較模糊,不過用于體積光這種本身就不是很清晰的渲染對象倒是很適合。
體積貼圖
光線追蹤重要的應用之一就是體積渲染。shadertoy中的體積渲染大多是使用隱式參數方程和實時算法生成噪音來制造體積的Distance Field。這種方法對于不熟悉數學的人來說難度有點大,也不適合美術人員創作。所以體積渲染時最常用的還是用Houdini等軟件生成體積貼圖。
目前主流游戲引擎還沒有全面支持3DTexture,所以我們要用體積切片的方法模擬3DTexture。Houdini和Blender都有方法渲染體積切片。渲染好的切片按照順序組成一張平鋪貼圖。
?
在采樣的時候,先確定采樣點的所處z軸位置上下兩張貼圖,在uv位置采樣兩次,然后通過z軸lerp兩個采樣數據,就可以得到采樣點的密度數據了。
引擎集成
將光線追蹤的體積渲染集成到游戲引擎中會有兩個問題。
第一是作為體積渲染的載體Mesh。片面Mesh肯定是不合適的,因為轉一個角度可能就看不到了,應該選擇閉合的Mesh。這個Mesh應該仿照天空球方法,法線向內,因為如果法線向外,進入Mesh內部就沒辦法顯示了。
第二是和場景現有物體的遮擋問題。解決方案是獲得場景的深度信息,做光線追蹤的時候反過來從場景的深度位置向視點進行追蹤,這樣就能完美實現遮擋了。如果做正向光線追蹤就需要在每次循環的時候檢查一下深度信息,做無謂的消耗。
?
總結
以上是生活随笔為你收集整理的游戏中的实时光线追踪技术与技巧的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 游戏引擎算法探究:游戏核心之固定流水线
- 下一篇: 快节奏多人游戏同步:技术与算法的实现