今天主程給我好好講了一下靜態批處理的問題,記下來的筆記心得~ 轉載請標明出處http://www.cnblogs.com/zblade/
1、靜態批處理的時間點
1)在游戲導出的時候,在player setting中勾選static batching,這樣在導出包的時候就進行批處理,導出來的包就會比較大
2 ) 在游戲場景中勾選場景物體的static選項,在加載該場景的時候,會進行一次靜態批處理的合並,這樣導出來的包不大,但是在加載的時候會使得內存變大。
2、靜態批處理的基本原理
場景中有4個物體,ABCD,如果都勾選靜態選項,在進行靜態批處理的時候,引擎會判斷這四個物體是否共用同一渲染材質。
如果共用同一渲染材質,則會將這四個物體視為可以批處理的對象,引擎會基於單個渲染對象的大小拷貝出3個,總共變為4個mesh,此時這4個mesh會存在一個index buffer中,此時會讓資源占用的內存變大4倍,這樣在渲染的時候,是將這個更大的mesh傳遞給GPU進行渲染操作的。
3、為什么要用靜態批處理?
在游戲的運行中,有時候CPU的瓶頸也會至關重要。如果CPU的運行速度較慢,則GPU會出現等待CPU的情況,此時游戲主要受到CPU的限制。
CPU在游戲中的主要分工,主要分為兩個部分:設置渲染狀態和調用DC。 其中設置渲染狀態屬於比較重要的分工,對於加載到游戲中的資源和對象等,CPU需要計算其頂點相關的矩陣,渲染所用的貼圖,渲染所用到的材質和shader,渲染所用到的燈光等。
如果每個物體的材質和貼圖等都不一樣,此時CPU的主要工作就是設置這些物體的渲染狀態(當然調用DC也會更多,但此時渲染狀態的改變更消耗性能,也就是setPass),游戲的運行會比較緩慢。所以在常見的游戲中,對於大量的不需要改變位置的物體,都會采用靜態批處理的方式來解決渲染狀態的瓶頸。
采用批處理的方式,對於相同渲染材質的物體,會合並成一個更大的渲染對象mesh來進行渲染,這時候設置合並后的渲染對象的渲染狀態,與設置合並前的多個渲染對象的渲染狀態相比會大大減小次數。
此外對於大部分的渲染對象,主要的判斷依據就是渲染狀態和位置矩陣相關的參數。如果渲染狀態一致,則基本可以視為同一個批處理的對象,然后對於位置矩陣進行單獨的設置即可。其實在引擎的內部,對於需要渲染的對象也會進行一個渲染排序,會優先將渲染狀態相同的排在一起進行設置,這樣渲染狀態的切換就不會過於頻繁。
通過批處理的方式來降低渲染狀態的切換次數,可以極大的優化CPU的渲染瓶頸,所以在很多時候會采用靜態批處理的方式來優化CPU的瓶頸。
4、對於靜態批處理后的物體,如何決定其可視?
對於靜態批處理后的物體,比如ABCD,那么如何在實際的游戲中去具體的渲染ABCD中的那幾個可見(位於相機的視錐體內)? 這需要解釋一下批處理的合並方式:在unity5中,會構建一個更大的內存buffer空間,依次存放ABCD的數據。
在渲染A的時候,會調用DX的接口來取這份buffer中的指定起始點和長度的數據出來,傳遞到GPU中進行渲染。如果需要渲染AD兩個對象,則會在前面的基礎上,再將整體取出來(因為D存在末尾),然后傳遞到GPU中進行渲染。注意此時是整體傳遞A或者ABCD的數據,不會在CPU進行裁剪的工作。具體的A的哪部分可見,是在GPU的頂點裁剪過程中進行的。
此時相當於要進行兩次渲染,渲染的次數增大了,這樣當然會帶來一定的性能損耗,但是相對於渲染狀態的設置改變帶來的性能損耗,是可以接受的。游戲中如果大量的物體都采用靜態批處理,此時會出現很大的內存buffer,如果渲染頭和尾部的物體,則會使得渲染數據過大(CPU傳遞給GPU),帶來較大性能損耗,所以可以在游戲中對靜態批處理對象進行一個分塊的處理。將場景中的對象分成多個塊,每個塊的大小可以依據一個經驗值來設置,此時就會出現多個靜態批處理的操作,而不是統一的一個靜態批處理操作。具體的分塊操作取決於具體的項目的場景大小,可以多次測試得到一個經驗值來進行設置。
后面對於動態批處理的原理,待我學習請教后再補上~
