黃聰
(咸寧職業(yè)技術(shù)學(xué)院 湖北省咸寧市 437100)
OpensSceneGraph(OSG)是一個(gè)跨平臺(tái)開源場景圖形程序開發(fā)接口。它作為中間件為應(yīng)用軟件提供了各種高級(jí)渲染特性,IO,以及空間結(jié)構(gòu)組織函數(shù)。它封裝并提供許多提升程序運(yùn)行性能的算法,利用顯示列表、OpenGL 狀態(tài)排序、著色語言、LOD 等方法提高效率,提供了絕大多數(shù)主流數(shù)據(jù)格式的直接數(shù)據(jù)接口(包括圖片、三維模型,以及字體等),同時(shí)支持腳本語言系統(tǒng)Python、Tcl、Lua 等。
當(dāng)應(yīng)用程序不再使用場景圖形時(shí),OSG 使用內(nèi)存引用計(jì)數(shù)器(referencecounted memory)來自動(dòng)釋放場景圖形節(jié)點(diǎn),OSG的內(nèi)存管理機(jī)制將在最后一個(gè)指向根節(jié)點(diǎn)的指針被釋放時(shí),釋放整個(gè)場景圖形。這種內(nèi)存引用計(jì)數(shù)機(jī)制包含以下兩個(gè)組件:基類osg::Referenced 和智能指針模板類ref_ptr<>。當(dāng)創(chuàng)建任何繼承自Referenced 的節(jié)點(diǎn)時(shí),程序切不可直接釋放其內(nèi)存空間,也不要用標(biāo)準(zhǔn)C++指針變量長時(shí)間保存繼承自Referenced 類的對(duì)象指針,否則編譯時(shí)會(huì)提示錯(cuò)誤信息。在osg::Reference 類成員函數(shù)中,有兩個(gè)成員函數(shù)ref()和unref(),二者主要用來控制內(nèi)存計(jì)數(shù),程序不要隨意改變內(nèi)存計(jì)數(shù)器的值。運(yùn)算符dynamic_cast 的主要作用是將基類的指針或者引用安全地轉(zhuǎn)換為派生類的指針或者引用,然后用派生類的指針或者引用調(diào)用非虛函數(shù),需要注意的是,在類層次間進(jìn)行轉(zhuǎn)換時(shí),基類型至少含有虛函數(shù)才能進(jìn)行這種轉(zhuǎn)換。開發(fā)者在編寫代碼時(shí)為避免出現(xiàn)內(nèi)存泄漏和指針懸掛問題,應(yīng)編寫清潔的代碼。
場景管理是OSG 渲染引擎的核心部分,OSG 利用包圍體層次包圍體層次(Bounding Volume Hierarchy,BVH)來實(shí)現(xiàn)場景圖形的管理。通過綜合使用包圍球(Bounding Sphere)和包圍盒(Bounding Box)這兩種形式來盡可能達(dá)到最佳的場景組織和訪問性能。當(dāng)有節(jié)點(diǎn)樹中某節(jié)點(diǎn)發(fā)生變化時(shí),需要重新計(jì)算該節(jié)點(diǎn)包圍球的大小和位置,一直遞歸到根節(jié)點(diǎn),從而維護(hù)整個(gè)BVH 樹。場景圖形采用一種自頂向下的、分層的樹狀數(shù)據(jù)結(jié)構(gòu)來組織空間數(shù)據(jù)集,場景圖形樹的頂部是一個(gè)根節(jié)點(diǎn),從根節(jié)點(diǎn)向下延伸,各個(gè)組節(jié)點(diǎn)中包含幾何信息和渲染狀態(tài)信息,各個(gè)葉節(jié)點(diǎn)包含了構(gòu)成場景中物體的實(shí)際幾何信息。場景樹包含的不同類型節(jié)點(diǎn)可以執(zhí)行各種不同的功能,如開關(guān)節(jié)點(diǎn)可設(shè)置子節(jié)點(diǎn)是否可用;細(xì)節(jié)層次節(jié)點(diǎn)可根據(jù)觀察者的距離調(diào)用不同的子節(jié)點(diǎn);變換節(jié)點(diǎn)可改變子節(jié)點(diǎn)幾何體的坐標(biāo)變換狀態(tài)。簡單的場景可能只有一個(gè)Camera,復(fù)雜的場景可能有多個(gè)Camera,不同的Camara 從不同的角度看向同一個(gè)場景時(shí),可能看到不同的場景,在渲染的時(shí)候,通過遍歷Camera,已完成渲染。不同的節(jié)點(diǎn)實(shí)現(xiàn)不同的功能,開發(fā)者應(yīng)根據(jù)需要靈活應(yīng)用,同時(shí)選擇合適的角度以觀察主場景。
OSG 中的osg::NodeVisitor 是對(duì)訪問器模式思想的具體實(shí)現(xiàn),訪問器的設(shè)計(jì)允許應(yīng)用程序?qū)⒛硞€(gè)特定節(jié)點(diǎn)的指定函數(shù)應(yīng)用到場景中的所有節(jié)點(diǎn)。通常的做法是繼承自osg::NodeVisitor 這個(gè)虛基類,重載apply()方法以獲取各個(gè)節(jié)點(diǎn)的屬性或者修改節(jié)點(diǎn)的屬性,在程序中調(diào)用accept()方法關(guān)聯(lián)需要訪問的節(jié)點(diǎn),并啟動(dòng)訪問器進(jìn)行遍歷。這種做法主要適用于一個(gè)對(duì)象結(jié)構(gòu)包含很多類對(duì)象,這些類對(duì)象有不同的接口,而想對(duì)它們實(shí)施一些依賴于其具體類的操作。如果對(duì)象結(jié)構(gòu)類經(jīng)常改變,那么可能在類中定義這些新的操作比較好。根據(jù)功能需要,可設(shè)置頂點(diǎn)訪問器,紋理訪問器,節(jié)點(diǎn)訪問器,編寫的訪問器重載基類的apply()函數(shù)以實(shí)現(xiàn)相應(yīng)功能,例如要查找指定的節(jié)點(diǎn)時(shí),判斷某個(gè)節(jié)點(diǎn)名稱是否與要查找的節(jié)點(diǎn)名稱一樣,將找到的節(jié)點(diǎn)添加到自己的節(jié)點(diǎn)列表或者從節(jié)點(diǎn)列表刪除。
OSG 采用狀態(tài)機(jī)機(jī)制osg::StateSet 來跟蹤所用的渲染狀態(tài),被狀態(tài)機(jī)管理的渲染狀態(tài)有:光照lights、材質(zhì)materials、紋理textures 等,它主要管理渲染屬性和渲染模式。將一個(gè)場景圖形關(guān)聯(lián)到一個(gè)實(shí)例化的osgViewer::Viewer 對(duì)象進(jìn)行渲染。因?yàn)閂iewer類的osg::Camera 對(duì)象管理模型-視圖矩陣,可通過控制Camera對(duì)象來改變每一幀的視口顯示或者設(shè)置清屏顏色。在動(dòng)態(tài)修改場景圖形時(shí)應(yīng)避免與揀選及繪制線程發(fā)生沖突。OSG 支持絕大部分OpenGL 固定功能管道(fixed function pipeline)渲染,如Alpha 檢驗(yàn),剪切平面,深度和模板檢驗(yàn),霧效,點(diǎn)和線的光柵化等。在程序中設(shè)置osg::StateSet 渲染狀態(tài),但應(yīng)使關(guān)聯(lián)到場景圖形的StateSet 最小化,減少一次場景圖形遍歷中所耗費(fèi)的工作量,從而減少內(nèi)存的占用。默認(rèn)情況下,所有的節(jié)點(diǎn)渲染狀態(tài)都繼承父節(jié)點(diǎn)的渲染狀態(tài),除非開發(fā)者該表節(jié)點(diǎn)的渲染狀態(tài)或者繼承模式。OSG 的渲染歸納起來包括三個(gè)階段:用戶階段、更新數(shù)據(jù)階段、場景的管理階段,最終利用renderingTraversals()函數(shù)完成場景的揀選和繪制工作。
紋理映射即紋理貼圖,使用紋理映射可以大大提高三維物體的真實(shí)感,達(dá)到良好的顯示效果。OSG 全面支持OpenGL 的紋理映射機(jī)制,OSG 加載紋理并把紋理送達(dá)GUP 的過程中,對(duì)紋理進(jìn)行了縮放和歸一化處理。對(duì)紋理的操作主要包括一維紋理、二維紋理、三維紋理、多重紋理、Mipmap 紋理和壓縮紋理等。二維紋理映射中紋理坐標(biāo)與幾何體的頂點(diǎn)坐標(biāo)一一對(duì)應(yīng)。多重紋理映射是多個(gè)二維紋理映射的疊加,對(duì)于不同的紋理屬性對(duì)象需要指定不同的紋理單元及紋理坐標(biāo),否則不會(huì)啟用該紋理單位或者該紋理單元會(huì)被覆蓋。Mipmap 紋理映射需要指定各層的紋理圖像數(shù)據(jù),用以避免圖像縮放時(shí)出現(xiàn)的抖動(dòng)或者閃爍現(xiàn)象,同時(shí)減少不必要的渲染負(fù)擔(dān)。程序員除了可以使用TextureRectangle 紋理映射,還可以自動(dòng)生成紋理坐標(biāo),以實(shí)現(xiàn)使用紋理貼圖生成模型的輪廓線或者光澤模型對(duì)任意環(huán)境的反射。
OSG 的回調(diào)機(jī)制主要有如下三種:osg::Node、osg::Drawable、osg::Camera。osg::Node 在OSG 執(zhí)行更新和揀選遍歷時(shí)進(jìn)行回調(diào);osg::Drawable 在揀選和繪制遍歷時(shí)進(jìn)行回調(diào);osg::Camera在更新遍歷時(shí)進(jìn)行回調(diào)。目前經(jīng)常開發(fā)者經(jīng)常使用節(jié)點(diǎn)回調(diào)(NodeCallback)和事件回調(diào)(EventCallback)。使用節(jié)點(diǎn)回調(diào)需重載operator()方法,以實(shí)現(xiàn)場景的動(dòng)態(tài)更新。當(dāng)交互事件觸發(fā),如操作鍵盤、鼠標(biāo)、改變窗口或者點(diǎn)選場景中的某節(jié)點(diǎn),事件回調(diào)不僅要重載operator()方法,還需創(chuàng)建事件訪問器并重載handle()方法,將回調(diào)實(shí)例關(guān)聯(lián)所需對(duì)象,如setUpdateCallback(),setEvent Callback(),setCullCallback(),setReadFileCallback()等。所有的事件均在osgViewer::Viewer::eventTraversal 中進(jìn)行,它將每個(gè)事件都發(fā)送到_eventHandlers 中的每個(gè)事件處理器中,經(jīng)過層層過濾,最終的操作由osgGA::GUIEventHandler 進(jìn)行處理。
OSG 使用一些工具類來實(shí)現(xiàn)一些相互獨(dú)立的功能,例如:osgParticle 粒子系統(tǒng)、osgText 文字處理與顯示、osgShadow 陰影、osgFX 擴(kuò)展庫、osgAL 三維立體聲音等。osgParticle 采用Billboard與色彩融合技術(shù),生成非常真實(shí)的粒子效果。osgText 有第三方插件FreeType 支持,用很小的點(diǎn)產(chǎn)生良好的輸出,顯示高質(zhì)量的文字。osgShadow 用來控制渲染實(shí)時(shí)陰影,渲染的時(shí)候要標(biāo)記出陰影投影對(duì)象和陰影接收對(duì)象。osgFX 擴(kuò)展庫是OSG 的附加庫,它定義了一系列定義好的特殊效果,這些效果可以添加到OSG 的節(jié)點(diǎn)中,如異性光照特效、凹凸貼圖特效、卡通渲染特效、刻線特效、立方圖鏡面高光特效等。osgAL 提供三維位置音效,它支持的聲源的最大數(shù)量由電腦的顯卡決定,但最多不應(yīng)超過32 個(gè)聲源,否則程序會(huì)出錯(cuò)。
OSG 具有跨平臺(tái)的特性,可運(yùn)行在所有Windows、Linux、IOS、Android 等操作系統(tǒng)平臺(tái),支持嵌入式設(shè)備。此外,OSG 可以運(yùn)行在多核的CPU 和GPU 上,因?yàn)樗鼘?duì)OpenGL 顯示列表、紋理單元、繪制遍歷等過程實(shí)施了保護(hù)措施,以實(shí)現(xiàn)異構(gòu)模式下的混合編程,可以通過osgViewer 配置當(dāng)前OSG 應(yīng)用程序的線程模型,渲染管線的不同階段可以單獨(dú)作為一個(gè)線程也可以在一個(gè)線程中串行執(zhí)行。它還支持各種UI,如Qt、MFC、SDL、GLUT、Wxwidget 等,分析研究Qt 的工作原理與信號(hào)槽消息機(jī)制,可編碼實(shí)現(xiàn)基于OSG與Qt 的應(yīng)用程序。
OSG 在三維應(yīng)用程序的開發(fā)中扮演著重要的角色,廣泛應(yīng)用于地理信息系統(tǒng)(GIS),計(jì)算機(jī)輔助設(shè)計(jì)(CAD),建模和數(shù)字內(nèi)容創(chuàng)作(DCC),數(shù)據(jù)庫開發(fā),可視化(飛機(jī)、船舶、車輛等仿真)、三維建模、虛擬現(xiàn)實(shí)(VR)、教育、動(dòng)畫和游戲等領(lǐng)域。
OpenSceneGraph 作為一種優(yōu)秀的開源三維程序渲染引擎,它完全是由標(biāo)準(zhǔn)C++程序和OpenGL 編寫,充分利用STL 和設(shè)計(jì)模式,讓開發(fā)者避免復(fù)雜的底層圖形實(shí)現(xiàn)和優(yōu)化,為三維圖形應(yīng)用程序的開發(fā)提供了很多方便,同時(shí),它在性能、可擴(kuò)展性、可移植性等方面具有極大優(yōu)勢(shì),能更加快速創(chuàng)建高性能、跨平臺(tái)的交互式圖形程序,廣泛應(yīng)用于三維可視化仿真、游戲、虛擬現(xiàn)實(shí)等高性能圖形應(yīng)用程序設(shè)計(jì)中。