模型資料作渲染優化時遇到的問題

千里馬肝發表於2014-03-22

前提:美術很隨意得使用貼圖、材質,大量的材質雖然名稱不同,但是實際上材質屬性是相同的。

於是,在匯出時,在依次處理材質時,應該將新的材質屬性與已經收集到的材質進行對比,如果是相同的,則使用已存在的材質。

同時,雖然mesh中的submesh其實是根據MatID來作劃分,但是一般情況下,mesh中的submesh的vertex decl通常是完全相同的。

那麼其實可以將所有相同的vertex decl的submesh合併在同一個geometry(VB)中,submesh使用不同的index buffer來繪製,減少繪製時的VB切換。

於是,就有了shared geometry的共用,如果submesh的vertex decl與之不同(例如ABC是diffuseMap,DE是diffuseMap + specularMap,FGH是diffuseMap + specularMap + normalMap),則自己使用獨立的geometry來繪製。

另外,還要對於mesh中所有的submesh所使用的material進行排序,以減少不必要的state切換。

而且還有一個好處是,material的數量、mesh的大小都會減少,意味著減少了磁碟IO和檔案解析所需要的時間。

 

接下來,就是本文的重點出現了。

問題總有2個:

1. 想象中優化後的場景目錄的檔案數量和大小,都應該會相應減少。但實際中發現,的確大多數模型資料都減少了十幾K到幾十K不等,但是少數模型的mesh尺寸變大了。

這個現象很奇怪,為了分析原因,我使用了工具對兩者進行了二進位制對比。

有意思的是,變大的檔案,例如之前的十六進位制資料為: AB CD EF GH,變大的資料變成AB CD 00 00 EF GH 00 00。

經驗告訴我,肯定是某些原先使用16bits描述的數值,現在變成32bits了。

相信朋友們已經猜到了原因,即合併submesh之前,每一個geometry大小都是65535以內,於是16bits IB就夠了

合併之後,vertex數量超過了65535,於是我的匯出外掛自動切換為32bits IB來描述了

通過搜尋資料,瞭解到10年前的GPU對於32bits IB的處理,除了頻寬上略有影響之外,並不會有額外的效能懲罰

而隨之優化帶來的batch減少以及VB等state切換所帶來的FPS提升,我的結論是這樣的優化是值得的

進一步的優化思考是,我目前是使用的triangle list儲存的IB,即一個face使用3個index;如果改為triangle trip,那麼IB是很有可能控制在65535之內的

 

2. 美術不一定會將同一個物體的多個子物體合併(Attach),例如手機:顯示螢幕、外殼、電池、天線,是分開為多個mesh存在,然後合成一個group。

這樣子並不會影響實際使用中的操作,因為畢竟scene中還是有一個叫“手機”的node。

但是理論上,我們還是希望這幾個物體合併在一起,甚至想到說,既然上述的material和geometry的優化,那為什麼不把整個場景都在匯出時自動merge到一起呢?

然後我想當然得寫了一個maxscript,在匯出之前會自動將場景中所有的mesh合併在一起。

但是實際情況是,雖然感覺上應該會更流暢,單個scene在觀察時也會有些許提升,但是當畫面是由多個scene分塊構成時,camera frustum的cull就廢掉了。

哪怕只有scene A的一棵小草被看到,整個scene都會被繪製出來,反而會影響到渲染效率。

 

優化無止境,同學需努力。

相關文章