精選文章

SmallBurger Asset Home

  SmallBurger

2022年12月31日 星期六

用MRT來優化SSAO在行動平台的性能

 對於行動平台使用深度貼圖,有經驗的人應該都知道Unity曾經不管三七二十一,只要是gles,一律走perDepthPass,而不走CopyDepth的流程,其實這個限制應該只是有在使用硬件MSAA的時候,才有這個問題,這曾經困擾了許多人,後來官方在新的版本做調整,讓大家鬆了口氣…

我在測試官方的ScreenSpaceAmbientOcclusion時,發現他的Depth Normals模式,不管是不是AfterOpaque,一律都走perDepthNormalPass,這對行動行台非常不友善,就跟perDepthPass是一樣的問題,雖然他有提供純Depth模式+AfterOpaque可以避免這個問題,但沒有normal效果就是比較差,所以便開啟了MRT + SSAO之旅(許多人把MRT跟延遲渲染畫上等號,但其實是可以應用在優化處理上)

執行步驟如下:

  1. 設計一個SetupScreenNormalMRTPass來處理MRT RenderTarget的設定,在BeforeRenderingOpaques時執行,這樣就可以在Render opaque之前把MRT畫布設定好,不過要記得只能在GameView中進行,因為目前在SceneView下使用MRT會造成沒辦法正常刷新的錯誤,反正底層本來就有PreDepthNromal的處理,這邊要注意的是CameraNormalMap的資料不是浮點數貼圖,因為MRT格式本來就要跟ColorRenderTarget一樣。
  2. 另外製作一個SSAOPass,跟原生的差別主要處理如果GameView就走MRT模式,如果是SceneView就直接呼叫ConfigureInput(ScriptableRenderPassInput.Normal),讓底層的DepthNormalOnlyPass來進行處理,其他的代碼跟原生的沒什麼區別。
  3. 再來是Shader的部份,我們在常規的Pass加入了一個#pragma multi_compile _ PROCESS_MRT_NORMAL,主要用來控制在GameView時才會走MRT輸出normal,而SceneView時,則交給常規的DepthNormals Pass來輸出normal。
  4. 最後是SSAO後處理Shader,基本上跟原生完全一樣,只是把取用Normal的部份分成來源是MRT還是常規的CameraNormal,如果是MRT的因為不是浮點貼圖的關係,所以我們要做UnPackNormalMap處理,如果是原生的CameraNormal的話,因為是浮點貼圖,所以就不用做UnPackNormalMap。

原生的FrameDebugger如下,會多了DepthNormalPrepass:


MRTSSAO的FrameDebugger如下,少了DepthNormalPrepass:


相關視頻如下:



Dream continues in...

沒有留言:

張貼留言