精選文章

SmallBurger Asset Home

  SmallBurger

2023年2月10日 星期五

關於FairyGUI或GUI以StackingCamera受到RenderScale影響的解決方案

自從URP問世之後,ScaleRender便在Unity成為主流,他是優化行動裝置3D渲染的一個好方法,當然之前也是有不少人在默認管線下做過這類的應用…

後來URP也加入了類似默認管線疊合(Stacking)渲染的處理流程,但稍微有研究的人就會發現他會受RenderScale參數的影響,如果拿來畫UI的話,那有關字及ICON的顯示可能會是場災難。
有人說那就用Overlay模式來畫UI就好,但專案還是會有一些特殊的需求要用Camera來畫,另外像FairyGUI大部份都是用Camera來渲染的系統,就影響很大了,也總不能為了UI的品質來禁用RenderScale的參數。

之前沒使用過FairyGUI,因為工作關係接觸了之後,發現他與URP整合上有一些問題,主要是大部份都是用Camera來畫,這樣一來就得走StackingRender的流程,不像UGUI還有Overlay模式可用,於是開啟了FitRenderScaleURP之旅。

目標:

  1. 讓畫UI的Camera可以有RenderScale = 1.0的屏幕解析度
  2. 可以依序疊合渲染
  3. 不使用額外的全屏渲染RenderTexture

最直覺的想法,應該就是開一個全屏的RenderTexture來畫UI,但有經驗的人都知道,渲染貼圖是沒辦法壓縮的,內存占用非常大,對行動裝置來說能省則省,所以這個方式不合適,目前看起來最好的方式應該是可以直接畫到FrameBuffer。不知道大家有沒有發現,RenderPipelineAsset裡有一個參數叫IntermediateTexture這個參數,其實他是用來控制是否要強制走RenderTexture的流程,經測試後,發現我們只要把這個參數設Auto且當RenderScale為1.0的時候,他就會嘗試使用FrameBuffer來畫,另外其他的條件是不可以使用DepthTexture及OpaqueTexture,所以這提供了我們可以不改URP的原代碼,直接畫到FrameBuffer的方法。




不過目前這裡,我還是會維持DepthTexture及OpaqueTexture的參數是勾選的狀態,因為專案實際上就是有需求,這裡我們會利用Camera的覆蓋參數來解決這個問題,也就是畫UI的Camera我們會用覆蓋掉的方式來處理。


接下來就是今天的主角FitRenderScaleControler這個腳本,基本上只要把它掛在對應的Camera就可以,他主要的運作原理就是當這個Camera被畫到的時候,我們就把RenderScale參數設為1,然這個Camera畫完後,我們就設回原本的參數,基本上只要傾聽BeginCameraRendering及endCameraRendering這兩個事件就可以達到目的。

我們可以在FrameDebugger的畫面看到,他是直接畫到FrameBuffer,而不是RenderTextrure


另外還有一個要注意的細節,就是我們疊合上去的BaseCamera,要記得把BackgroundType選成Uninitialized,這樣才不會把原本畫好的東西清掉,才疊得上去…



FitRenderScaleControler的代碼也只是簡單的幾行…



相關視頻如下:


不過目前這樣的做法也不是完全沒有缺點,如果是想有3D UI(比方角色血條或TitleBar之類的),要跟3D物件(比方山擋住)排序之類的,這時候因為參考不到DepthBuffer,所以就只能放到MainCamera畫。

最後再附上相關的Github連結:

AkilarLiao / FitRenderScaleURP

沒有留言:

張貼留言