1.背景介紹
1.1 OSG介紹
OSG的全稱:OpenSceneGraph,它是一個開放源碼,跨平臺的圖形開發包,它為諸如飛行器仿真,游戲,虛擬現實,科學計算可視化這樣的高性能圖形應用程序開發而設計。
它基于場景圖的概念,它提供一個在OpenGL之上的面向對象的框架,從而能把開發者從實現和優化底層圖形的調用中解脫出來,并且它為圖形應用程序的快速開發提供很多附加的實用工具。
基于OSG的典型應用:Delta3D(美國海軍研究院開發的全功能游戲與仿真引擎)、osgEarth(三維數字地球引擎庫)
1.2 LOD介紹
是指根據物體模型的結點在顯示環境中所處的位置和重要度,決定物體渲染的資源分配,降低非重要物體的面數和細節度,從而獲得高效率的渲染運算。在OSG的場景結點組織結構中,專門提供了場景結點osg::LOD來表達不同的細節層次模型。其中,osg::LOD結點作為父節點,每個子節點作為一個細節層次,設置不同的視域,在不同的視域下顯示相應的子節點。
主要3個過程: 生成,切換,選擇。
最主要的問題:如何實現平滑過渡。
實現方式:最差的方式是后臺準備多個模型,根據距離直接切換,缺點是切換時感覺突兀。
(1)線性混合方式:對兩個離散層級的模型進行混合,缺點是加大系統內存和計算開銷
(2)透明度混合:在臨切時,一個逐步透明,另一個逐步顯示,淡入淡出。
(3)最優方式:實時算法,將相鄰頂點或邊進行合并,靠算法進行模型數據坍處理,逐步坍塌頂點,離得越遠,模型越小。
一般LOD都是根據距離來做切換過渡的,少數基于時間和投影面積等其他特定需求的.
2.渲染框架
2.1 幀渲染機制
- ?Update 更新 Cull 篩選? Draw 繪制
- 渲染幀:每一次場景更新,篩選,繪制的過程。
- advance():一幀經歷的時間、幀數以及棄用對象的刪除,獲取幀率及顯示狀態信息等;
- eventTraversal():執行用戶設置的EventCallback,為所有的用戶交互和系統事件提供一個響應的機制; 它必須在每一幀的仿真過程中,取出已經發生的所有事件,摒棄那些對場景不會有助益的(例如,在視口以外發生的鼠標移動事件和胡亂點擊),依次交付給各個事件處理器 ( EventVistor事件遍歷器),最后清空現有的事件隊列eventQueue ,等待下一幀的到來。
- updateTraversal():處理用戶的更新回調對象之外,還要負責更新攝像機的位置,并且更新分頁數據庫DatabasePager 和圖像庫ImagePager 的內容。
- 更新回調與事件回調最大的不同在于:每當一個用戶交互或系統事件產生時,每一個節點(以及Drawable 對象)的事件回調都會被調用一次;而節點(以及Drawable 對象)的更新回調只會在每幀中被調用一次( NodeVistor 節點遍歷器)。這一區別決定了我們應當在什么時候使用事件回調,以及在什么時候使用更新回調。
- renderingTraversals():場景的渲染遍歷工作。
2.2 更新機制
2.3 視景管理
2.4 數據分頁管理
分為DatabasePager管理和ImagePager管理。
在三維場景中可以采用數據分頁的方式進行動態調度。這里“分頁”的意思是隨著視口范圍的變化,場景只加載和渲染當前視口范圍內數據,并將離開視口范圍內的數據清除內存(可以設定不同的數據卸載策略),不再渲染。保證內存中只有有限的數據量,場景的每一幀也只有有限的數據被送到圖形渲染管道,從而提高渲染性能。
執行時機
在每一幀刷新的節點更新回調中處理
動態調度
OSG源代碼中提供PagedLOD來進行模型的動態調度。在不同的視域下,PagedLOD動態讀取不同細節層次的結點模型,實現了分頁LOD顯示。OSG內部采用osgDB::DatabasePager類來管理場景結點的動態調度,場景循環每一幀的時候,會將一段時間內不在當前視圖范圍內的場景子樹卸載掉,并加載新進入到當前視圖范圍的新場景子樹。OSG采用了多線程的方式來完成上述工作。
具體工作步驟:
- 在每一幀中通過一個UpdateSceneGraph()來進行動態調度。
- DatabasePager::removeExpiredSubgraphs:用于去除已經過期的場景子樹;
- DatabasePager::addLoadedDataToSceneGraph:用于向場景圖形中添加新載入的數據。osgDB::DatabasePager 類執行的是這一工作:每一幀的更新遍歷執行到updateSceneGraph 函數時,都會自動將“一段時間之內始終不在當前頁面上”的場景子樹去除,并將“新載入到當前頁面”的場景子樹加入渲染,這里所說的“頁面”往往指的就是用戶的視野范圍。這些分頁和節點管理的工作如果由渲染循環來完成的話,恐怕是費時又費力的,對于場景的顯示速度有較大的影響,因此,DatabasePager 中內置了專用于相關工作處理的DatabaseThread?線程。
2.5 DatabaseThread工作機制
???????????????????????????????? 場景主線程交互邏輯
2.6 渲染消息處理流程
使用EventQueue::TakeEvents函數,把GraphicsWindow圖形窗口對象gw的事件隊列保存到指定的變量 gw_events中。