當前位置:首頁 >教程首頁 > 遊戲程序 > Unity3D遊戲開發工程師班 >遊戲圖形批量渲染及優化:Unity實例化渲染

遊戲圖形批量渲染及優化:Unity實例化渲染

發布時間:2020-11-19 13:51:09

上回  遊戲圖形批量渲染及優化:Unity動態合批技術 簡單總結了一下動態合批,這次我們繼續說說Unity實例化渲染。

| 實例化渲染

當我們想要呈現這樣的場景:一片茂密的森林、廣闊的草原或崎嶇的山路時,會發現在這些場景中存在大量重複性元素:樹木、草和岩石。

1.webp.jpg

仙境怕是也不過如此吧

它們都使用了相同的模型,或者模型的種類很少,比如:樹可能隻有幾種;但為了做出差異化,它們的顏色略有不同,高低參差不齊,當然位置也各不相同。

使用靜態合批來處理它們(假設它們都沒有動畫),是不合適的。因為數量太多(林子大了,多少樹都有),所以合並後的網格體積可能非常大,這會引起內存的增加;而且,這個合並後的網格還是由大量重複網格組成的,不劃算。

使用動態合批來處理他們,雖然不會“合並”網格,但是仍然需要在渲染前遍曆所有頂點,進行空間變換的操作;雖然單顆樹、石頭的頂點數量可能不多,但由於數量很多,所以也會在一定程度上增加CPU性能的開銷,沒必要。

那麼,對於場景中這些模型重複、數量多的渲染需求,有沒有適合的批處理策略呢?有吧,實例化渲染就是為了解決這樣的問題。

| 簡述工作原理

實例化渲染,是通過調用“特殊”的渲染接口,由GPU完成的“批處理”。

它與傳統的渲染方式相比,最大的差別在於:調用渲染命令時需要告知GPU這次渲染的次數(繪製N個)。當GPU接到這個命令時,就會連續繪製N個物體到我們的屏幕上,其效率遠高於連續調用N次傳統渲染命令的和(一次繪製一個)。

舉個例子,假設希望在屏幕上繪製出兩個顏色、位置均不同的箱子。如果使用傳統的渲染,則需要調用兩次渲染命令(DrawCall = 2),分別為:畫一個紅箱子 和 畫一個綠箱子。

2.webp.jpg

兩個顏色、位置各異的箱子

如果使用實例化渲染,則隻需要調用一次渲染命令(DrawCall = 1),並且附帶一個參數2(表示繪製兩個)即可。

當然,如果隻是這樣,那GPU就會把兩個箱子畫在相同的位置上。所以我們還需要告訴GPU兩個箱子各自的位置(其實是轉換矩陣)以及顏色。

這個位置和顏色我們會按照數組的方式傳遞給GPU,大概這個樣子吧:

3.webp.jpg

分別傳遞保存位置和顏色的數組

那接下來GPU在進行渲染時,就會在渲染每一個箱子的時候,根據當前箱子的索引(第幾個),拿到正確的屬性(位置、顏色)來進行繪製了。

4.webp.jpg

一個簡單的實例化渲染流程

| Unity是如何處理實例化的

我們通過一個簡單的場景,來看一下Unity為實例化渲染做了什麼。

5.webp.jpg

實例化渲染兩個彩色箱子

6.webp.jpg

顏色屬性通過MaterialPropertyBlock傳入

通過GPA觀察Unity做了什麼。

7.png

GPA中的VertexBuffer和IndexBuffer中的信息

注:Unity默認Cube網格,包含24個頂點和36個索引。

頂點緩衝區Size = (Position(float3)

+ Normal(float3)

+ Tangent(float4)

+ TexCoord(float2)

+ TexCoord1(float2)) x 24 = 1344Byte

索引緩衝區Size = Index(ushort) x 36 = 72Byte

可見,頂點、索引緩衝區內,確實隻有一個網格的數據。

那麼GPU如何判斷每個Cube的繪製位置,及其顏色呢?

結合引擎為Dx平台生成的shader(我的測試環境使用的是Pc),可以很容易找到對應的數據。

8.webp.jpg

轉換矩陣及顏色被分別填入Constant Buffer中

9.webp.jpg

Constant Buffer中的矩陣(Dx為行向量)

10.webp.jpg

Constant Buffer中的屬性(顏色)

可見,渲染時GPU可以通過當前實例化單位的索引,從Buffer中獲取到對應的屬性,完成正確的繪製。

| Unity中啟用實例化渲染

當然,相比於上述無用的知識點,如何在Unity中使用實例化渲染可能更為重要。

在Unity中可以通過自動或手動的方式,啟用實例化渲染。

自動啟用實例化渲染

使用支持實例化渲染的Shader,並勾選材質球上的啟用開關,Unity便會對滿足條件的物體,自動開啟實例化渲染。

11.webp.jpg

有這個選項即表示該Shader支持實例化渲染

自定義Shader

如果你希望自己的Shader也支持實例化渲染,應重點注意以下內容:

#pragma multi_compile_instancing

啟用實例化渲染(材質球上將出現啟用實例化的勾選框);

UNITY_VERTEX_INPUT_INSTANCE_ID

在a2v及v2f的結構中定義實例化索引下標(SV_InstanceID ),也就是當前渲染單位的索引,用於從Constant Buffer中提取正確的屬性(做顯示差異化用);

UNITY_INSTANCING_BUFFER_START ~ END

在這個起止區域內定義屬性,才能在著色器中正確的根據索引提取出當前渲染單位所對應的屬性;

UNITY_SETUP_INSTANCE_ID

定義在著色器的起始位置,使頂點著色器(或片段著色器)可以正確的訪問到實例化單位的索引;

UNITY_ACCESS_INSTANCED_PROP

根據索引訪問到這個單位對應的屬性,如上麵例子中每個箱子的顏色屬性。

這裏隻是簡述一些相對重要的內容(湊些字數),官方文檔中有更詳細內容,建議優先了解。

手動實例化渲染

使用  Graphics.DrawMeshInstanced 和 Graphics.DrawMeshInstancedIndirect 來手動執行 GPU 實例化,詳見官方文檔中的解釋,這裏就不再贅述了。

| 實例化渲染的使用要求

並非所有設備都可以使用實例化渲染。

在Unity官方文檔中,列舉了各平台支持實例化渲染的最低要求。

12.webp.jpg

官方文檔中對支持實例化渲染的最低API要求

當然,我們也可以通過引擎中SystemInfo.supportsInstancing屬性來判斷環境是否支持實例化渲染。

那支持實例化渲染的機器占比大概是多少呢?由於國內大多數遊戲公司都是以手遊項目糊口。所以開發者可能會更多關注其在安卓平台上的情況。

根據Android開發者的官方數據顯示,截至2020年8月30日,約88%的活躍安卓設備,都已經支持實例化渲染,所以基本上可以放心使用。

13.webp.jpg

android開發者官網發布的活躍設備OpenGL ES版本占比信息

| 與靜、動態合批的差異

靜、動態合批實質上是將可以合批的對象真正的合並成一個大物體後,再通知GPU進行渲染,也就是其頂點索引緩衝區中必須包含全部參與合批對象的頂點信息;因此,可以認為是CPU完成的批處理。

實例化渲染是對網格信息的重複利用,無論最終要渲染出幾個單位,其頂點和索引緩衝區內都隻有一份數據,可以認為是GPU完成的批處理。

其實這麼總結也有點問題,本質上講:動、靜態合批解決的是合批問題,也就是先有大量存在的單位,再通過一些手段合並成為批次;而實例化渲染其實是個複製的事兒,是從少量複製為大量,隻是利用了它“可以通過傳入屬性實現差異化”的特點,在某些條件下達到了與合批相同的效果。

| 簡單總結靜、動態合批及實例化渲染

無論是靜態合批、動態合批或實例化渲染,本質上並無孰優孰劣,它們都隻是提高渲染效率的解決方案,也都有自己適合的場景或擅長解決的問題。

個人以為:

如果你的場景中存在多數靜止的、使用了不同網格、相同材質的物體,特別是當你的相機通常隻能照到一部分物體時(如第一視角),可以優先嚐試下靜態合批,通過犧牲一些內存來提升渲染效率;

針對那些運動的、網格頂點數很少、材質相同的物體,比如飛行的各種箭矢、炮彈等,使用動態合批,通過增加一些CPU處理頂點的性能開銷,來提升渲染效率,也許是不錯的選擇;

如果有大量模型相同、材質相同、或盡管表現上有一些不同,但仍然可以通過屬性來實現這些差異化的物體時,啟用實例化渲染通常可以在很大程度上提升渲染效率。

|  寫在最後

按計劃下次更新的內容應該是“優化骨骼蒙皮動畫,以及兩種常用的批量渲染方式”,但覺得內容有點多,所以將其分為兩個部分;因此,下次更新的內容變為“優化骨骼蒙皮動畫”,而“兩種常用的骨骼蒙皮動畫單位的批量渲染方式”,將作為本係列的最後一次更新內容。

下回見嘍。

作者:枸杞憂天

來源:偶爾學學Unity公眾號

华体会hth体育网 賞析
  • 2101期學員李思庭作品

    2101期學員李思庭作品

  • 2104期學員林雪茹作品

    2104期學員林雪茹作品

  • 2107期學員趙淩作品

    2107期學員趙淩作品

  • 2107期學員趙燃作品

    2107期學員趙燃作品

  • 2106期學員徐正浩作品

    2106期學員徐正浩作品

  • 2106期學員弓莉作品

    2106期學員弓莉作品

  • 2105期學員白羽新作品

    2105期學員白羽新作品

  • 2107期學員王佳蕊作品

    2107期學員王佳蕊作品

專業問題谘詢

你擔心的問題,火星幫你解答

微信掃碼入群領福利

掃碼領福利最新AI資訊

點擊谘詢
添加老師微信,馬上領取免費課程資源

1. 打開微信掃一掃,掃描左側二維碼

2. 添加老師微信,馬上領取免費課程資源

×

同學您好!

您已成功報名0元試學活動,老師會在第一時間與您取得聯係,請保持電話暢通!
確定