URP中增加屏幕空間陰影開關

陰影實現過程

 

在UniversalRenderPipeline中(以下簡稱URP),默認使用的是屏幕空間陰影(Screen Space Shadow), 通過 ScreenSpaceShadowResolvePass 這個類來實現,如果不想使用該陰影的話,就需要修改URP的代碼。

首先要明確屏幕空間陰影的實現過程,

  1. 生成陰影圖,_MainLightShadowmapTexture
  2. 生成屏幕空間深度圖,_CameraDepthTexture
  3. 根據_CameraDepthTexture和裁切空間座標(ClipSpacePos)重建出世界空間座標(WorldSpacePos)
  4. 根據WorldSpacePos 和 _MainLightWorldToShadow矩陣把座標轉換到陰影空間中,生成 _ScreenSpaceShadowmapTexture
  5. 在RenderOpaques階段對_ScreenSpaceShadowmapTexture進行採樣,計算陰影值
     

然後要確定修改後的實現過程,

  1. 生成陰影圖,_MainLightShadowmapTexture
  2. 根據 WorldSpacePos 和 _MainLightWorldToShadow 矩陣把座標轉換到陰影空間中
  3. 在RenderOpaques階段對 _MainLightShadowmapTexture 進行採樣,計算陰影值

對比兩個實現過程可以發現屏幕空間陰影比常規陰影的實現過程多了兩個步驟,

  1. 生成屏幕空間深度圖階段,即Depth Prepass階段
  2. 生成屏幕空間陰影圖階段,即Resolve Shadow階段

由此推測,屏幕空間陰影可能比常規陰影更耗時。

 

具體修改內容

 

考慮到增加的是一個切換屏幕空間陰影和常規陰影的開關,因此使用者希望的應該就是一個checkbox之類的勾選框,只有兩種狀態,清晰明瞭。在把Camera組件的參數看了一遍以後,我覺着這個開關應該加在Render Shadows選項後面,位置如圖:

Inspector面板的修改比較常規,參考已有的Camera屬性即可,其中 Render Shadows 選項在代碼中對應的屬性是 UniversalAdditionalCameraData 類的 renderShadows 屬性,如圖:

在ForwardRenderer的Setup方法中設置是否需要DepthPrepass階段和ResolveScreenSpaceShadow階段,

 

當選項勾選時開啓關鍵字  _SCREEN_SPACE_SHADOW, 用來在Shader中區分是用哪種陰影,在MainLightShadowCasterPass中設置,

Shader中所作的修改有:

        1. 在Lit.shader的UniversalForward pass中定義關鍵字 _SCREEN_SPACE_SHADOW

        2.使用常規陰影時需要在片元階段用到世界空間座標,因此需要修改vert 到 frag的結構體

 

      3. 在LitForwardPass.hlsl文件的 InitializeInputData 方法中修改給ShadowCoord屬性的賦值邏輯,當使用屏幕空間陰影時ShadowCoord在頂點着色器中計算,使用常規陰影時在片元着色器中計算,

                                                    頂點着色器中的修改:

                                                                               片元着色器中的修改:

        4. 修改SHADOWS_SCREEN宏的判斷條件

 

耗時對比

 

做完這些修改後就可以實現切換屏幕空間陰影和常規陰影了,使用URP自帶的測試場景SampleScene,打包到Android設備上(小米8SE)運行,(打包過程有些困擾,感謝車徵大佬提供debug思路),使用Profiler查看渲染耗時,只看RenderCamera事件,屏幕空間陰影在13ms到17ms,常規陰影在7ms到15ms,可以看出常規陰影比屏幕空間陰影用時少一些。以下是同樣場景,同樣攝像機角度保持不變只是切換陰影開關時的15幀數據,只列出兩種陰影有差異的一些渲染事件耗時:

 

總結

根據在真機上運行的profiler數據,可以看出常規陰影的耗時比屏幕空間陰影更少,基本可以達到8~9ms的級別,而且還可以少使用一張RT,即 _ScreenSpaceShadowmapTexture,如果後續效果中不需要使用屏幕空間深度的,還可以把_CameraDepthTexture這張RT也省掉,同時渲染時不執行Depth Prepass階段,耗時進一步減少。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章