渲染之靜態批處理

2021-10-20 07:50:42 字數 2488 閱讀 4947

操作方法

在unity場景的右側屬性面板中直接勾選static屬性,那麼就可以在遊戲引擎中完成靜態批處理

原理

滿足條件:使用相同的材質球,模型是禁止的

標明為 static 的靜態物件,如果在使用相同材質球的條件下,在build(專案打包)的時候unity會自動地提取

這些共享材質的靜態模型的vertex buffer和index buffer。根據其擺放在場景中的位置等最終狀態資訊,將這

些模型的頂點資料變換到世界空間下,儲存在新構建的大vertex buffer和index buffer中。並且記錄每乙個子

模型的index buffer資料在構建的大index buffer中的起始及結束位置

盜一張圖:從下面這張圖中,我們可以清楚的看到,可以靜態批處理的模型,他們的頂點都被儲存到了乙個更大的頂點buffer中,並且是一次性傳給了gpu,同時也把各自的索引儲存到了乙個更大的buffer陣列中,也是一次性傳給了gpu,但是記錄下了各自的起始位置和長度

再看一張圖:對於繪製每乙個模型的時候,還是正常繪製,傳送渲染狀態,呼叫繪製命令,drallcall的數量並沒有減少,但是卻可以極大減少cpu和gpu的計算

原因

1:從矩陣的角度說

靜態批處理在進行頂點合併到統一的大buffer中之前,還對頂點做了一些變換,根據縮放旋轉平移以及繼承關係,算出世界模型矩陣,然後把頂點buffer中頂點乘以這個矩陣,然後再存入到那個統一的大頂點buffer中,就是把頂點變換到了世界座標系下,也就是說,我們在shader中不需要對頂點進行pxvxmxpos操作了,只需要pxvxpos了,減少了一次矩陣的運算,那麼在cpu端,由於不需要每一幀都去計算世界模型矩陣然後把世界模型矩陣傳給gpu了,所以也省去了自身關於模型矩陣的計算維護,但是第一次還是需要的

2:從狀態機的角度來說

gpu是乙個狀態機,不改變狀態就是最好的,切換狀態耗時,這個狀態就包括很多了,可以進行批處理的,他們的狀態幾乎都是一致的,比如頂點資料(位置,uv,法線,索引),混合,texture等,對於頂點資料來說,可以通過起始位置和長度來取資料,所以他們的合併也可以達到狀態的一致,靜態批處理下的模型都是緊挨著一次一次繪製的,所以對於gpu來說,它的狀態幾乎沒有改變,那麼也就不會有什麼效能損失,這就好像合併了drawcall了一樣,

靜態批處理的弊端

舉乙個常見的樹的例子,如果森林中有1000棵樹,這些樹模型公用乙個mesh,如果我們不開啟靜態批處理的話,那麼在資源包中就只有乙份mesh資料,在載入到記憶體中也只有乙份,在每一幀渲染的時候,在記憶體發往gpu的時候,可能會發1000份,那麼視訊記憶體中就有1000份頂點資料,這很明顯drawcall數量過多,效能大幅降低;如果我們給這1000棵樹開啟靜態批處理的話,那麼構建的時候,每乙個樹模型都會在資源包中持有乙份mesh資料,在遊戲執行時候,記憶體中一下子多了999份mesh資料,只是這些資料被全部轉換到了世界座標系下,然後再一次性的合併到乙個更大的頂點buffer中,發往gpu中;

問題1:對於記憶體中一下子多了999份,這個是可以理解的,因為在shader那邊不要頂點位置乘以模型世界矩陣了,所以必須要確切的知道頂點在世界座標系下的位置,所以預先對每乙個靜態模型做了乙份轉換到世界座標系下的資料存在本地,當然如果你的模型的數量是動態生成的,那就不會增大資源包

總結

靜態批處理不會降低drawcall,但會極大的減少狀態切換,而gpu狀態切換是特別耗時的,如果我們只是增加drawcall,但每一次繪製的時候,gpu的狀態幾乎不切換,那麼效能將沒啥影響,可靜態批處理會將所有可以批處理的模型的網格資料全部合併到一張更大的頂點和索引buffer中,這將增大cpu端的記憶體,當這個buffer發往gpu以後,就貯藏在gpu中了,cpu這邊可以刪除,我們說的增大記憶體應該指的是第一次在cpu這邊合併,然後發往gpu,第一次cpu端的記憶體確實會增大,可也只是一幀的時間,最好真正增大的是gpu

在每一次需要渲染那些模型的時候,會從這個更大的buffer中取起始點和長度,然後傳送到gpu,他們的繪製順序一定是緊挨著的!比如你有8個模型可以靜態批處理,那這8個模型一定是緊挨著的,且在第一次載入的時候,存在總的buffer中的頂點資料是已經乘以世界座標系的,只需要乘以一次,後面這些資料是需要乘以v*p就好了

每一幀將可以合批的網格進行合併,然後一次將頂點和索引buffer傳送給gpu,這個降低了drawcall,但由於進行了網格合併操作,這個會增加cpu端的效能消耗,所以處理的頂點數目不易過大

unity 渲染批處理

unity 可以在執行時組合一系列物件,並使用單個繪製呼叫統一繪製。這種操作稱之為 批處理 unity 可以批處理的物件越多,可以獲得的渲染效能就越好 就 cpu 而言 只有共享同一種材質的物件才可以批處理。更改 renderer.material 將建立材料的副本,應該使用 renderer.sh...

Unity 動態批處理和靜態批處理

為了提高遊戲效能,降低遊戲執行時的drawcall,unity會對網格頂點進行批處理,而批處理又分成了動態批處理和靜態批處理 優點 不用自己做任何事情,unity會在遊戲中自動進行動態批處理,只要滿足下述條件。在unity中,要進行動態批處理需要滿足以下條件 原理 unity會檢測哪些gameobj...

批處理之命令

一 基本介紹 批處理是一種簡化的指令碼語言,而指令碼,就是使用一種特定的描述性語言,依據一定的格式編寫的可執行性檔案。批處理就是對某物件進行批量處理,其實也就是逐行書寫在命令列中會用到的各種命令,複雜的情況就比如使用if,for,goto等命令控制程式的執行。系統在執行批處理程式的時候,首先會掃瞄整...