1. 程式人生 > >開源3D圖形渲染引擎OGRE學習筆記

開源3D圖形渲染引擎OGRE學習筆記

參考資料:

電子書:《Pro OGRE 3D Programming》中文翻譯本

官方wiki: http://www.ogre3d.org/wiki/index.php/Main_Page

中文網站(有電子書下載)http://www.ogre3d.cn/

 

 

OGRE(Object-oriented Graphics Rendering Engine)(Ogre, 食人魔),是一款成熟、穩定、可靠、靈活、跨平臺、而且擁有豐富功能開源實時3D圖形渲染引擎(並不是遊戲引擎),由ogre3d.org社群維護,遵守LGPL(GNU Lesser General Public License

)協議。

 

 

同類其他開源引擎:

1. Irrlicht(鬼火)

2. Nebula(星雲)

3. klayGE

 

 

OGRE引擎特性:

·全面並同等的支援OpenGLDirect3D 

·全面支援WindowsLinux以及Mac OS X平臺

·其完全的面向物件設計,允許您通過外掛和子類毫不費力地擴充套件引擎的功能。

 

 

Ogre 3D的名字中包含“3D”是很貼切的,因為那就是它所能做的所有事情。它不能處理使用者輸入,不能管理你的遊戲狀態,不能做網路通訊,不能播放聲音。它只是做為一個

3D渲染引擎被設計出來,並且那就是它唯一的應用。因為專業,所以它總是能夠很好的完成它本分的任務。(雖然Ogre引擎中也會包含比如輸入系統等一些簡單的實現,但官方的說法一般是:這只是為了支援演示程式所提供的,不建議你在自己實際的應用中使用。你需要在Ogre去中去尋找其他的庫來完善你自己的工具箱。)

 

 

當今大多數軟體都會依賴於其他軟體或者開發包中提供的外部功能,這樣可以讓軟體的開發在別人已經存在的成果之上,避免了重複製造輪子。如果不需要對常用的功能重複實現,這樣做最直觀的好處就是促使工作團隊更集中精力解決他們自身軟體中所存在的問題,進而產生出更高質量的產品。而且隨著開源社群的發展,越來越多優秀的軟體或者程式庫可以從網路上免費得到。不過更多的依賴專案也意味著需要相對更復雜的編譯環境設定,甚至有時候要編譯構建所依賴的專案原始碼產生。如果依賴了一些在活躍開發期的專案,就意味著有可能需要經常更新。

OGRE的最小依賴集有FreeType, OpenIL, zziplib

 

 

我能用OGRE 做遊戲嗎?是的,你能。並不象許多其他的3D引擎,OGRE並不是適合任何型別的遊戲。由於開發的原因,OGRE只適合第一人稱射擊遊戲。OGRE特別適合製作3D 遊戲。

 

 

Ogre 3D自發布以來,被成功地應用於諸多三維模擬領域。其中包括網路遊戲和一些商業的三維模擬專案。

在國內,基於OGRE的網遊大作MMO已經有幾款了,其中包括搜狐的《天龍八部》、吉位元的《問鼎》、深圳網域的《華夏2》以及久遊的《瘋狂飆車》。

 

 

 

Ogre是一個龐大而紛雜的物件和模組集合,如果初學者希望直接從物件列表中得到什麼資訊的話,可能會感到眼暈。但是事實上事情遠沒有這麼複雜,當在你真正開始使用的時候,你會體會到Ogre完全面向物件設計的好處,絕大部分的細節都被隱藏在成熟的層次結構之中,只需要你簡單的呼叫,就能實現很絢麗的功能。對於3D API或者其他一些引擎的使用者而言,很少能有這種經歷,甚至也不會去這麼想:在Ogre可以用很少的程式碼來完成一個完整而漂亮的3D應用程式。

 

 

 

 

引擎這個術語暗示Ogre 3D 為你的3D圖形的應用程式提供了“強大的動力”,進而允許你更多關注應用程式細節而不是一個3D場景的渲染過程。作為應用程式的中介軟體,Ogre扮演了一個專注於處理了三維空間場景的角色。如果你熟悉Direct3D或者OpenGL,你會知道直接寫一個圖形程式需要多少程式碼,當你瞭解Ogre讓你可以用很少量的程式碼來構建一個完整的三維場景(也有用在其他的方面,我們將在之後的文章中介紹)的時候,你就會慶幸有Ogre的存在。

Ogre通過面向物件的方法實現了這樣的一個入口,從實際應用進入到3D引擎具體的本職工作把基本幾何體渲染到目標區域(一般情況下指的是CRTLCD顯示裝置的螢幕快取,但也有例外)。如果你曾經使用傳統而基本的方法進行過3D應用程式開發(換句話說,就是有使用OpenGL或者Direct3D這種底層API的經驗),你會了解到它們有一些相似而且繁瑣的過程:通過呼叫API設定渲染狀態;通過呼叫API傳送幾何體資訊;通過呼叫API通知GPU渲染;清理;返回到第一步,直到渲染完一幀進入下一幀。這個過程會讓你陷入紛雜的API操作之中,相對於真正的應用,可能你會被浪費在基本的幾何體操作中去。

如果使用面向物件的方法來渲染幾何體,就可以從幾何體級別的處理工作中抽離出來,轉而處理具體的場景和在場景中的物體。其中的物體包括:可活動的物體、靜態物體組成的場景本身、燈光、攝像機以及其他。你只需簡單的把物體放到場景之中,Ogre會幫助你完成雜亂的幾何渲染處理,從而脫離對呼叫API的依賴。而且你也可以通過簡單的方法來操作場景中的物體來代替矩陣變換:例如,可以簡單的通過角度或者弧度來控制物體在不同空間內旋轉(包括本地空間、世界空間和父節點空間),而不必要通過矩陣的變換這種抽象的方法來操作實現變換。簡而言之,面向物件讓你可以處理更具象的物體、屬性和方法。而不用處理抽象的頂點列表、三角形列表、旋轉矩陣等底層概念。

Ogre的面向物件框架提供了包括全部渲染過程的物件模型。渲染系統Render system)把複雜且不同的底層API(比如OpenGLDirect3D)的功能抽象成一個統一的操作介面;場景圖Scene graph)也被抽象成為另外的一組介面,並且允許使用不同的場景管理演算法實現“即插即用”的效果;所有可渲染(Renderable)物件,不論是動態還是靜態,都被抽象出一組介面,用來被具體的渲染操作呼叫,比如技術(Technique)和其中的通路(Pass);可活動物件提供了一組通用介面接受各種各樣的操作方法。

Ogre做到了場景圖與場景內容的分離。首先,Ogre對場景圖的操作維持在介面級別;它並不關心去操作圖形的具體演算法實現。換言之,Ogre只是通過訊號(它們的方法)來操作場景圖,進而忽略了具體的演算法實現。其次,Ogre場景圖介面只負責維護場景結構。節點中沒有包含任何固有的內容和管理方法具體的內容被放置到一種可渲染(Renderable)物件之中,它提供了場景中全部幾何圖形(包括活動的的或者其他所有的)。它們的渲染的屬性(也可以說是材質)被包含在實體(Entity)物件中,在實體物件裡面同樣包含著一個或多個子實體(SubEntity)物件,這些子實體才是是真正可以被渲染物件

場景管理器可以幫助你建立具體的場景節點(Scene Node)。所謂的場景節點就是你在場景中實際移動變換的基本單元。場景中具體的場景內容需要掛接到場景節點上才能顯示。這裡所說的內容在大多數情況下指的就是實體Entity)。實體繼承於活動物件(MovableObject),並通過場景管理器來進行建立。如果你有已經有一個的實體的具體例項,你就可以把它繫結到已經存在的場景節點上。基本上實體都是從硬碟上的“.mesh”檔案載入的模型來構建。當場景內容掛接到場景節點之後,你就可以通過場景節點來管理實體了,注意,是變換場景節點,而不是場景內容

 

其中活動物件(MobeableObject)可以直接操作所有幾何體和渲染屬性。它並不是場景節點的子類,而是掛接到場景節點中(可以理解為通過組合代替繼承)。這意味著如果你需要,程式中的場景節點可以不用瞭解與之相關的可渲染物件的任何細節。也意味著你可以擴充套件,改變,重寫,或者其他改變場景圖的實現,而不會影響場景內容介面的設計和實現;他們徹底獨立於場景圖。場景圖甚至可以完全修改而不會影響任何內容類。

 

反過來說也同樣適用:場景圖同樣不需要對所掛接的場景內容節點有任何瞭解,只要通過所用的介面來通知就可以完成所需要的功能。因為這些出色的設計,Ogre甚至可以完成對“使用者自定義(user-defined)”內容節點的掛接。如果你決定構造一個擁有環繞立體聲的場景,你可以把各種音效實現自定義節點,然後無縫的掛接到場景中。自定義的場景節點只需要實現一個簡單的介面,就可以把定製資料掛接到場景中任意的節點上。

 

 

 

可擴充套件性強的外掛體系。舉例來說,Ogre在介面層來管理場景圖的實現,這樣就意味著使用者沒有被限制在一定要使用哪幾種場景管理演算法的侷限內。使用者可以把任何自己程式需要的場景演算法“插入”到Ogre程式庫中,並且它們可以和Ogre本身提供的演算法一樣的良好的工作。如果在某個程式中需要KD-Tree場景演算法的支援,你只要簡單的按照Ogre定義的介面實現一個KD-Tree場景圖的演算法,並把它插入到你的Ogre程式中就能很好的使用了。

 

 

靈活的渲染佇列。Ogre採用了“場景佇列”。這是一個容易理解的概念:Ogre將需要渲染的內容分別放在多個有序佇列之中,並且佇列之間也是有自己的順序,Ogre分別渲染每個佇列。

 

 

 

健壯的材質系統。Ogre的材質是由一個或者多個渲染技術(Technique)組成,每個技術中又含有多個渲染通路(Pass)。這種通路指的是一個單獨的渲染通道,它是Ogre材質渲染中的一個基本單元。換句話說,物件的每一個渲染通路將導致一次對圖形硬體的繪圖呼叫。

 

 

獨有的模型和骨骼檔案格式(*.mesh*.skeleton)Ogre使用了自己獨有的模型和骨骼資料格式。這也等於告訴你Ogre無法直接使用其他第三方的模型格式,例如商業遊戲中的模型。如果你使用二進位制格式來儲存模型和骨骼資料檔案,Ogre可以快速高效的載這些資料。這些二進位制檔案可以通過外部匯出器或者離線工具(命令列OgreXMLConverter工具,在附錄A討論)來生成。當然,如果你願意,OgreXMLConverter工具內部的類是允許在你自己的應用程式中使用的(假如你想從3D模型包中匯出模型資料到二進位制檔案)。通常有一種普遍的建立二進位制模型和骨骼檔案的方法,先把場景或者角色模型資料從3D工具中轉換到中間格式——可讀的XML格式(Ogre XML),然後再通過命令列工具轉換這個資料到二進位制。Ogre官方網站上提供了當前大多數3D模型工具(包括商業和開源)的匯出檔案外掛。其中包括Softimage|XSIAutodesk 3D Studio Max MayaBlender(還有很多沒有在這裡列舉出來,你可以到Ogre官方網站上去檢視詳細列表)。

 

 

Ogre支援三種動畫方式:骨骼動畫(Skeletal)、變形動畫(Morph)以及姿態動畫(Pose)。骨骼動畫是通過把頂點繫結到骨骼的骨頭(Bone)上來實現的(也被稱為矩陣調色蒙皮技術,或簡稱為蒙皮技術)。在物體上的每個頂點都可以同時被四塊獨立的骨頭影響,影響的具體力度取決於頂點對每塊骨頭分配的權重,當骨骼運動的時候,所有被它影響的頂點都根據骨頭的位置和權重來更新自身的位置。這種演算法可以模擬很多現實的頂點位移,例如可以很好的模擬在移動的胳膊的時候肩膀的外型的變化(更確切地說,因為當胳膊擡起的時候肩膀相應的肌肉會收縮)。目前Ogre還只能支援關鍵幀形式的正向動力學(FK)骨骼動畫;也就是說沒有提供對逆向動力學(IK)骨骼動畫的內建支援;如果你的美工在3D模型工具中使用了逆向動力學產生相應的動畫,這時候可以對骨骼每一幀進行取樣來轉換成正向動力學的骨骼動畫。通常來說,這些工作都可以在匯出外掛中很好的完成。變形動畫與姿態動畫都屬於頂點動畫技術。變形動畫儲存了頂點在每一關鍵幀的絕對位置,然後在執行時對兩個位置進行相應的插值計算,因為多個頂點的絕對位置無法疊,所以多個變形動畫之間無法相互混合成新的動畫。而姿態動畫的不同之處在於它儲存的是頂點的相對位置,因此多個姿態動畫的軌跡可被混合起來,進而創建出更復雜的頂點動畫。不過上面兩種型別的動畫都可以與骨骼動畫很好的混合使用。

 

 

 

合成器框架(Compositor frameworkOgre新加入的一個特性,它允許使用者在視口(Viewport)級別實現全屏的二維後處理(Postprocessing)特效。例如,你可以把視口中全屏的內容實現的發光或者朦朧處理、黑白渲染、銳化邊緣渲染。任何你能想象的對整個視口的操作都可以在合成器框架中實現。

 

 

 

資源Ogre中的定義是“所有渲染幾何體到渲染目標的資料所需要的資料”。這不僅包含模型骨骼材質,還包含表層Ovelary)指令碼和字型,以及有材質處理所需要的一些資源,比如合成器框架指令碼、GPU程式紋理

 

 

 

Root物件是一個Ogre應用程式的主入口點。因為它是整個Ogre引擎的外觀(Façade)類(請參考設計模式中的外觀模式),所以在這裡作為第一個被列出來的類,它提供了方便的呼叫整個Ogre每個子系統的介面。通過Root物件來開啟和停止Ogre是最簡單的一種方式;當你構造構造一個Root例項的時候你就啟動了整個Ogre,當析構的時候(讓它停止活動或者執行delete刪除它)Ogre也就關閉了。

 

 

資源管理器OGRE中的資源型別包括模型(Mesh,骨骼(Skeleton,材質指令碼(Material,GPU程式,紋理(Texture,合成器指令碼(Compositor,字型資訊(Font)等。

 

 

一般來說,開發者沒有必要直接對渲染系統(RenderSystem進行操作。因為渲染系統是Ogre對底層硬體APIOpenGL或者Direct3D)的一層抽象。儘管如此,你還是至少要了解渲染系統所建立的一個物件型別,即渲染目標(RenderTarget類。它是對Ogre中兩個重要概念的概括抽象:渲染到視窗和渲染到紋理

 

 

OGRE初始化:

Root * root = new Root(“plugins.cfg”, “ogre.cfg”, “ogre.log”);

bool rtn = root->showConfigDialog();

root->initialise(true, ”My Render Window”);

RenderWindow * window =root->getAutoCreatedWindow (); //建立render window

root->addFrameListener(myListener); //新增幀監聽

root->startRendering(); //開始render迴圈

 

 

 

plugins.cfg檔案:Ogre中所謂的外掛就是符合Ogre外掛介面的程式碼模組(在Windows下面是DLL檔案,在Linux下是.so檔案),比如場景管理(SceneManager)外掛和渲染系統(RenderSystem)外掛等。在啟動的Ogre時候,他會載入plugins.cfg配置檔案來檢視有哪些外掛可以被使用。

 

 

Ogre.cfg檔案:在啟動Ogre的時候,引擎提供了一個簡單的圖形介面,可以通過它來配置基本的渲染屬性。該配置檔案和那個圖形介面功能是一樣的。

 

 

Ogre渲染視窗的概念是唯一可以被系統用來渲染場景的地方。就如同現實世界中的畫布一樣,Ogre把你程式的內容畫到它的表面。為了實現這個目的,Ogre至少需要一個攝影機(Camera來“拍攝”你的場景,同時也需要一個或幾個視口(Viewport,用於存放攝影機的拍攝下來的“膠片”(和渲染視窗的功能有些類似)。

 

 

在呼叫startRendering()之後,Ogre就會不斷地渲染在你場景中所有能被渲染的東西。你可以通過關閉渲染視窗來結束這個過程(比如單擊視窗右上角的x圖示,或者在Windows工作列中右鍵選單中選擇關閉)。當你在註冊了幀監聽(Frame Listener,之後會介紹)物件,然後在回撥結束後返回一個false值給系統,同樣也能結束程式渲染。作為備用,Ogre還提供了一個可以在程式的任何地方呼叫的方法Root::getSingleton().queueEndRendering()來立刻結束程式。不過在使用startRendering()進行渲染的時候,最常用的辦法還是在幀監聽中返回false

 

 

場景管理器所做的工作:

在通常的情況下,Ogre的場景管理器會負責處理以下事情:

·在場景中建立和放置活動物體、燈光以及攝像機,並維護他們的在場景圖中的周遊和變換。

·載入和佈置世界地圖(World geometry,與活動實體不同,世界地圖是巨大且可以延伸的,通常情況下是不可移動的,比如一個完整的BSP地圖)。

·對場景查詢(Scene Queries)的支援,比如回答“在世界的某個原型空間內,都包含了那些物體”。

·剔除不可見物體並且將可見物體放入渲染佇列。

·根據當前和渲染物體的透檢視,對無方向的光源(Nondirectional Light)進行組織和排序(按由近到遠)。

·設定並且渲染場景中的陰影。

·渲染場景中的其他物體,如背景和天空盒

·傳送組織好的內容到渲染系統執行渲染

 

 

Ogre自身提供兩個場景管理器型別OctreeSceneManagerTerrainSceneManagerOctreeSceneManager是一個通用的場景管理器。TerrainSceneManager是一個為高度場場景優化的場景管理器。

 

對於程式的開發者而言,場景管理器的直接用途一般是用來建立場景中所使用的物件,比如:燈光、攝影機、實體、粒子系統以及公告欄這些活動物體,以及天空盒、靜態幾何體和世界地圖(World geometry)這些非活動物體。對於場景中存在的物體,不論是否能被渲染,都會交給場景管理器進行具體的管理工作。

 

場景管理器用場景節點來定義場景圖的結構。這些場景節點以層次的結構組織在場景管理器中:一個場景節點可以有一個父節點和任意數量的子節點。你可以對場景管理器中的節點進行繫結或者摘除操作;這裡提供一個簡單的辦法來關閉場景中的某個部分:只要把不希望渲染部分的根節點從場景圖中摘除下來,這個部分就不會被渲染了。場景節點必須通過建立它們的場景管理器來銷燬。

建立實體並進行移動、旋轉、縮放:先建立Entity,然後attach到場景節點,然後對場景節點進行移動、旋轉、縮放(translate, rotate/yaw/pitch/roll, scale)(注意:rotate是可以沿任意軸旋轉,yaw/pitch/roll分別只是沿著x/y/z三個軸旋轉)

 

 

 

場景管理起另外一個很重要的功用就是用來進行空間場景查詢(從場景中得到查詢的反饋資訊),其中包括:光線查詢(Ray Queries)、球體查詢(Sphere Queries)、邊界盒查詢(Bounding-Box Queries)、邊界平面查詢(Bounding-Plane Queries)以及相交查詢(Intersection Queries)。其中光線查詢返回與給定光線(空間中兩點組成的虛擬線)相交的物體資訊;球體查詢返回給定球體(通過球中點和半徑確定的空間區域)中所有包含的物體資訊;邊界盒查詢返回給定軸向包圍盒(通過兩個三維向量作為對角點產生的與空間軸平行的長方體空間)中所包含的物體資訊;邊界平面查詢返回與給定的無限延伸的平面相交物體的資訊;相交查詢返回與指定物體相交的所有物體資訊。所有的查詢過程都是可進行遮蔽操作的(Maskable),這意味著你可以通過這個功能過濾到你不需要的物件。

 

 

多個座標系,座標系方向如下:

座標系示例

 

 

 

動畫Ogre有兩種不同的操作動畫物件的方法,一種是通過關鍵幀,另外一種是通過控制器。關鍵幀之間的是動畫軌跡。Ogre支援下面幾種動畫軌跡型別(在同一軌跡中的所有關鍵幀必須使用相同型別):

數字動畫軌跡NumericAnimationTrack):與數字關鍵幀NumericKeyFrame)對應,每個關鍵幀中都儲存了相應的數字資料。這裡使用了AnyNumeric資料型別來儲存這些數值。在Ogre自身有一種特殊的資料結構被稱為Any,它很類似動態語言中的可變型別,可以用來儲存各種C++型別的資料。AnyNumericAny的子類,負責儲存各種數值型別,比如實數和整形。

節點動畫軌跡NodeAnimationTrack):與變換關鍵幀TransformKeyFrame)對應,每個關鍵幀都包含了兩個三元向量和一個四元數,分別用來表現節點在當前幀的位置、縮放以及方向。

頂點動畫軌跡VertexAnimationTrack):同時對應於頂點變形關鍵幀VertexMorphKeyFrame)和頂點姿態關鍵幀(VertexPoseKeyFrame),每個關鍵幀都儲存了特定時間的頂點位置資料,在姿態動畫(Pose)中還儲存了頂點混合權重。

 

 

你的應用程式控制Ogre中動畫的的主要途徑就是“動畫狀態(Animation State)”,程式碼中你可以通過這些名字來呼叫實體中的某個動畫部分,而物體則返回相應的動畫狀態以供你使用。其中包括以下動畫屬性:

長度:以秒為單位,獲得動畫片段的長度。

當前位置:得到或者設定當前播放的位置,換句話說是從動畫片段(而不是整個動畫)開始到當前位置所流逝的時間(秒)。

動畫名稱:儘管你可以通過物體本身得到所有的動畫列表,這裡仍然提供只讀屬性的動畫名稱用來在不知道動畫名字情況下呼叫。

迴圈:設定或者得到在動畫片段結束後是否迴圈播放。

啟用:設定或者得到這個動畫是否啟用。

權重:動畫可以被混合(但有相應的一些限制,在後面介紹)。這個屬性可以設定或者得到當動畫與其他動畫混合的時候的影響的權重。

 

 

程式碼繪製圖形或者模型可以使用ManualObject類。