目錄 |
|
本文探討網格體的壓縮存儲與背後的信息論,實現數據庫與虛幻引擎(UE)解耦,目的是僅僅將UE作爲一個渲染器,讓數據與渲染分離,以適應千萬級構件的項目需求。
網格體的屬性
首先需要明確,我們看到的3維模型都是中空的,基本都只是閉合的表面,這一點從“網格體”的名字也能看出。從存儲的角度看,網格體只是由一個個頂點組成,既沒有“面”也沒有“體”:因爲平面可以由3個點來確定,立體可以由閉合的面確定,不用額外存儲信息,以此達到壓縮最大化的目的。所以3維網格體看上去是由若干個三角形組成,存儲時都是一些點而已。一個完整的網格體(mesh)可以由一系列基本的幾何信息描述,它們包含:
中心點:網格體唯一的中心座標
頂點數組:相對於中心點的相對座標
三角形數組:各個頂點的下標索引,長度是3的倍數
紋理貼圖:貼到所有三角形表面上的2維圖片
UV座標數組:網格體降維映射到貼圖上的座標,長度等於頂點數
備用UV座標數組:網格體可以存儲多個UV,適應不同貼圖
材質屬性:除了紋理之外表面的物理屬性
切線數組:頂點相切於表面的切線,若不可微則有多條,長度等於頂點數
法線數組:頂點垂直於表面的法線,若非曲面則有多條,長度等於頂點數
頂點色數組:網格體的單調色,長度等於頂點數
其中有些信息是必要的,有些是可選的,有些是必要但可替換的。一般而言,頂點座標信息是首要的,雖然閉合的凸面體可以根據頂點信息演算出來,但這種情況很少,法線和切線可以根據三角形的位置和三點的順序來確定,如果只考慮純色材質,頂點色可以取代貼圖以節省體積,UV座標和紋理貼圖就可有可無了。所以存儲在PostGIS或者MongoDB中的每個網格體至少需要以下3個字段:
頂點:網格體的頂點座標列表
三角形:頂點之間組成的面,以及由三角順序決定的朝向(朝內/朝外)
UV座標+貼圖:決定網格體紋理的拉伸和平鋪
如果想要進一步壓縮,紋理貼圖可以替換成頂點色數組,但只能實現單調的表面着色,應用場景非常有限,接下來分析這些個字段的存儲格式。
中心點和頂點
頂點座標的數據存儲比較直觀,就是3個float32浮點數爲一組,無縫拼接的字節串,字節的數量是12的倍數,倍數=頂點數。
Base128:變長整數編碼
GPU接收的三角形數組是以頂點編號爲基礎,3個1組傳遞來實現的,所以三角形數組的長度是3的整數倍,倍數就是三角形的數量。因爲頂點編號是從0開始的自然數,所以三角形數組是一個自然數組,對於每個自然數,如果用定長整數編碼比如int16或int32無疑會造成空間浪費,這裏應當使用變長自然數編碼:Variable Length Quantity 或者叫Base128編碼。這種編碼可以將更小的自然數存儲在更短的字節中,比如0~127的整數只佔1個字節,原理並不複雜,可以參考這個規範:
https://github.com/zipack/spec/blob/master/spec.md#the-biased-vlq-natural-number
複合型網格體
對於結構上有公共部分,或者呈包含關係的多個網格體,在PostGIS中需要通過引用的方式存儲公共組件,虛幻引擎中也應該通過繼承等方式複用公共組件,從而以達到節省內存/外存的目的。虛幻引擎中,對於只有transformation屬性不同的同一種網格體,應當使用InstancedStaticMesh來暗示編譯器實現最大化的複用率,
PMC和RMC
PMC指ProceduralMeshComponent,是引擎原生提供的運行時mesh生成環境,它包括基本幾何信息和網格體之間的雙向轉換函數:GetSectionFromStaticMesh和CreateMeshSection,以及在構造函數中混合複用mesh的能力。在PMC的基礎之上,官方推薦的插件RMC(RuntimeMeshComponent)做了一些列性能優化和功能升級,包括使用多線程的計算力。
往期回顧
本文分享自微信公衆號 - WebHub(myWebHub)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。