在之前的文章中,我們使用兩個案例介紹並演示了 Unity URP Renderer Feature 的創建與使用(點擊回看)。今天,我們一起來學習一下 URP 中多相機的玩法。
Unity 中的攝像機的工作方式就像現實世界中的相機一樣:它捕獲三維空間中對象的視圖,並將其顯示在二維的平面上。
相對於 Unity 默認的渲染管線,Unity 通用渲染管線(URP)中的攝像機會有什麼不同之處呢?簡單概括為 5 點,我們來看下:
首先,在 URP 中具有「相機」組件的 GameObject 還必須具有「通用附加相機數據」組件(The Universal Additional Camera Data component)。如果我們的項目使用 URP,則在創建 Camera GameObject 時,Unity會自動添加通用附加 Camera Data 組件(如下圖粉紅色標識)。
我們不能從「相機 GameObject 」中刪除「通用附加相機數據」組件。附加相機數據組件擴展了相機組件的功能,並允許 URP 存儲與相機相關的其他數據。如果不使用腳本來控制和自定義 URP,則無需對 Universal Additiona Camera Data 組件執行任何操作。如果使用腳本來控制和自定義 URP,則可以通過腳本訪問攝像機的通用附加攝像機數據組件。(如果需要在腳本中頻繁訪問通用附加相機數據組件,則應緩存對其的引用,以避免不必要的 CPU 工作)
另一個不同點是通用渲染管線(URP)中設置了兩種 Render Type 渲染類型的相機:即「Base Camera」和「Overlay Camera」。
Base Camera 是 URP 中默認的攝像機類型。Base Camera 是可渲染到給定渲染目標的通用相機。要以 URP 渲染任何東西,我們的場景中必須至少有一個 Base Camera。我們可以單獨使用 Base Camera,也可以在相機堆棧 Camera Stack 中使用它。
Overlay Camera 是將其視圖呈現在另一個攝影機的輸出之上的攝影機。我們可以使用「Overlay Camera」來創建效果,例如車輛的駕駛艙。
然後就是相機堆棧(Camera Stack),可以讓我們將多個攝像機的輸出分層為單個組合輸出;我們必須使用「Camera Stack」系統將「Overlay Cameras」與一個或多個「Base Camera」結合使用。其中 Camera Stack 中的 Base Camera 確定了 Camera Stack 的大多數屬性。值得注意的是:我們不能單獨使用 Overlay Camera 這是不起作用的,因為不屬於 Camera Stack 的 Overlay Camera 不會執行其渲染循環的任何步驟,Overlay Cameras 只能用作 Camera Stack 的一部分。
並且在渲染場景時,URP 僅使用 Overlay Cameras 的以下部分屬性:Projection、FOV Axis、Field of View、Physical Camera properties、Clipping plans、Renderer、Clear Depth、Opaque Texture、Depth Texture、Render Shadows、Culling Mask、Occlusion Culling。
Unity 在 Inspector 中隱藏了所有其他未使用的屬性。我們可以使用腳本來訪問未使用的屬性,但是對這些未使用的屬性進行的任何更改都不會影響使用「Overlay Cameras」的任何「Camera Stack」的視覺輸出。我們也不能將後期處理應用於單個「Overlay Cameras」。但是,我們可以將後處理應用於單個 Base Camera 或 Camera Stack。Camera Stack 也是本篇文章重點介紹對象,後面我會進行實戰環節手把手帶大家進行操作。
第四點 The Volume system,可讓根據場景中給定的變換位置將後處理效果應用於相機;相機中的後期特效介紹不是本節的重點,但是我會在接下來的 Post-processing in the Universal Render Pipeline 中給大家重點介紹。
最後一點就是相機組件 The Camera component,在 Inspector 中展示特定於 URP 的一些屬性。
介紹完了 URP 相機的不同之處後,我們知道在通用渲染管線(URP)中可以使用多個攝影機,而且使用「Camera Stack」時,還可以有效地定義這些攝影機渲染的順序,那麼我們可以用多攝像機做點什麼效果呢?下面我給大家簡單介紹幾個:
01 堆棧相機(Camera Stack)可以將多個相機的輸出合併為單個輸出。通過相機堆棧,你可以在2D UI中加入3D模型,或者創建車輛駕駛艙的效果。如下圖所示:
02 將多個 Base Camera 或相機堆棧 Camera Stack 渲染到同一渲染目標。這使我們可以創建分屏渲染效果,效果展示如下。
03 將 Base Camera 或 Camera Stack 渲染為渲染紋理。可以創建諸如 CCTV 監視器之類的效果,效果如下。
當然你也可以結合使用這些工作方式獲得更複雜的效果。說了這麼多,大家有沒有心動?是不是已經迫不及待想開始學習如何使用呢?那麼接下來我就帶大家一起做個案例來講解下如何在 URP 中使用多相機技術。我們先來做一個簡單的分屏效果。
我們場景中有四個飛機,每個飛機都跟著一個 Base Camera。這裡我們重點看下 Viewport Rect(這個屬性只有在 Output Texture 選擇為 None 時候,也就是渲染到屏幕的時候才會顯示出來)的參數(如下圖中紅圈中所示),這裡的四個值指示這個 Base Camera 的視圖在屏幕上繪製的位置。其中 X 將繪製攝像機視圖的起始水平位置;Y 是將繪製攝像機視圖的起始垂直位置;W(寬度)攝像機輸出在屏幕上的寬度;H(高度)攝像機輸出在屏幕上的高度。
因為我們的屏幕坐標是左下角為(0,0),右上角的坐標是(1,1);第一個 Camera 我們輸出屏幕的左上角,所以這裡的值 X=0、Y=0.5、W=0.5、H=0.5。
第二個 Camera 我們輸出屏幕的右上角,所以這裡的值 X=0.5、Y=0.5、W=0.5、H=0.5。
第三個 Camera 我們輸出屏幕的左下角,所以這裡的值X=0、Y=0、W=0.5、H=0.5。第四個 Camera 我們輸出屏幕的右下角,所以這裡的值X=0.5、Y=0、W=0.5、H=0.5。接下來我們來用多相機實現一個稍微有難度的效果,我們要製作一個如上圖所示的效果,很容易想到我們可以創建一個 Base Camera 畫場景;接著創建兩個 Overlay Camera,一個畫駕駛艙,一個畫 UI;然後將兩個 Overlay Camera 攝像機疊加到 Base Camera 上採用 Camera Stack,得出最終的效果如下所示。這樣也可以實現最終效果的。但是我想稍微提高下複雜度!(但是這裡還是希望大家可以去親自嘗試下第一種方法),其實我這樣做是有原因的。因為我想儘可能多的帶大家了解URP攝像機的參數設置。
我們使用第二種方法,將這裡的畫駕駛艙的 Camera Render Type 改成了 Base Camera,如下圖所示。
URP 中的兩種 Render Type 的攝像機「Base Camera」和「Overlay Camera」的使用;也涉及到了採用相機堆棧 Camera Stack 創建車輛駕駛艙效果;重點是也用到了將一個 Base Camera 或者相機堆棧渲染到 Render Texture 上,創建如 CCTV 監視器的效果,如下圖中色箭頭標註所示。首先,我們創建第一個 Camera,這裡我們命名為 GameSence,這裡我們設置 Camera 的 Render Type 為 Base Camera,顧名思義這裡我們是用這個攝像機來渲染場景。然後,Rendering 中的 Priority 的規則是值越大優先級越高,優先級較高的攝像機繪製在優先級較低的攝像機的前面。這裡Priority的取值範圍是 [-100,100],這裡它的優先級最低,所以這裡我們給它取個值為-1。另外,由於第一個 Camera 這裡只負責畫場景,駕駛艙 Cockpit 與 UI 不參與其中,所以這裡的 Culling Mask 忽略這兩個層,如下圖所示。接下來,我們新建一個 RenderTexture 命名為 GameWorld,在 Output 屬性中,我們分配 Output Texture 為 GameWorld,則將此 Camera 的輸出渲染到一張名為 GameWorld 的 RenderTexture 供第二個畫駕駛艙的 Base Camera 進行採樣使用(如下圖所示:我們來找下這張 GameWorld 在場景中的引用有哪些,我們發現除了駕駛艙左右兩邊的監視器外駕駛艙前的主屏幕也對其進行了引用),如果這裡不做選擇的話,則輸出渲染為屏幕。最後,我們這個相機不做疊加處理,所以這裡的 Stack 不進行操作。到這裡第一個 Base Camera 攝像機已經配置完成。我們接著創建第二個 Base Camera,命名為 CockpitCamera;這個 Camera 是用來畫駕駛艙的,所以這裡我們的 Culling Mask 僅選擇為駕駛艙 Cockpit,如下圖所示。另外第二個 Camera 我們讓他輸出到屏幕,所以這裡 Output 中的 Output Texture 我們選擇為 None,選擇完成之後這裡會多出個參數 Target Display,這裡我們選擇為 DIsplay 1。
因為我們要將第三個類型 Overlay Camera 名為 UICamera 效果疊加到這裡,所以 Stack 這裡我們選擇添加 UICamera。
然後我們創建第三個 Camera 名 UICamera,將其類型選擇 Overlay Camera ,Culling Mask 僅選擇為 UI。
最後返回第二個 Base Camera,點擊 Stack 下的 + 號,將其添加到第二個 Camera 的 Stack 上,進行疊加從而得到了最終的效果(上面已經操作過了)。URP 在 Camera 中進行了多項優化,包括渲染順序優化以減少 Overdraw。使用「Camera Stack」時,可以有效地定義渲染這些攝影機的順序。但是,我們必須非常小心,因為不當的排序相機渲染順序導致過度的 Overdraw 從而影響 GPU 的性能。
理想情況下,我們使用的攝像頭應該儘可能的少(如我們可以使用render features來渲染更多的東西),並且要注意避免過多的透明材質重疊。而且也得實際項目實際考慮。
另外一個重要的點是:URP 場景如果包含多個攝像機,則 Unity 將以如下可預測的順序執行其剔除和渲染操作。這對我們後續進行渲染的優化工作很重要。Unity 逐幀執行一次以下操作:
01 Unity 獲取場景中所有激活的 Base Camera 的列表。
02 Unity 將處於激活狀態的 Base Camera 機分為兩類:將其視圖渲染為「渲染紋理」的攝像機和將其視圖渲染到屏幕的攝像機。
03 Unity 將按優先級順序對渲染到「渲染紋理」的 Base Camera 進行排序,以便最後繪製優先級值較高的攝影機。
04 對於每個渲染到「渲染紋理」的 Base Camera,Unity 執行以下步驟: 對 Base Camera 進行剔除操作(視錐體與 Culling Mask) 將 Base Camera 渲染到渲染紋理 對於 Base Camera 相機堆棧中一部分的每個 Overlay Camera,請按照相機堆棧中定義的順序進行操作:對 Overlay Camera 進行剔除操作
05 Unity將按優先順序對渲染到屏幕的 Base Camera 進行排序,以便最後繪製優先級值較高的攝像機。
06 對於渲染到屏幕上的每個 Base Camera,Unity執行以下步驟: 對 Base Camera 進行剔除操作 將 Base Camera 渲染到屏幕 對於 Base Camera 相機堆棧中一部分的每個 Overlay Camera,將按照相機堆棧中定義的順序進行操作:對 Overlay Camera 進行剔除操作
另外值得注意的是在目前版本的 URP 中,僅當使用 ForwardRenderer 時才支持「Overlay Camera」和「Camera Stack」。如果使用 2D 渲染器,則 Overlay Camera 將不執行其渲染循環的任何部分。
好的,今天就先講到這裡,希望大家繼續關注。
想要學習 URP 的朋友,歡迎加入 QQ 學習交流群,任何與URP相關的問題,都可以在群裡@我哦。
群名稱:Unity URP學習交流群
以下是本篇文章所用到的技術資料連結:
[1] URP手冊
https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.2/manual/index.html
[2] URP官方案例
https://github.com/Unity-Technologies/UniversalRenderingExamples
長按關注
第一時間了解Unity引擎動向,學習最新開發技巧