一、 引言
Irrlicht引擎是一個用C++書寫的高效能即時的3D引擎,可以應用於C++程式或者.NET語言中。通過使用Direct3D(Windows平台),OpenGL 1.2或它自己的軟體著色程式,可以實現該引擎的完全跨平台。儘管是開源的,該Irrlicht庫提供了可以在商業級的3D引擎上具有的藝術特性,例如動態陰影,粒子系統,角色動畫,室內和室外技術以及碰撞檢測等(見圖1)。
Irrlicht是一個德國神話故事中的一種動物的名字,它能夠發光和飛翔,可以在大部分的沼澤地附近發現它。單詞"Irrlicht"是兩個德國單詞("irr"意思是瘋狂的;而"Licht"意思是光)的組合。在英語中,它被譯為"鬼火"。
Irrlicht十分幸運地為一個巨大的活躍的Team Dev以大量的工程所支援。然而,因為Irrlicht主要由遊戲名家Nikolaus Gebhardt所設計,所以該遊戲在設計上十分連貫。你可以在網上到處發現有Irrlicht的增強程式,如可選用的地形產生器,入口產生器,輸出器,world層產生器,相關教程和編輯器等。而且,它獨立地建立了到Java,Perl,Ruby,BASIC,Python,LUA甚至更多種語言的綁定。而最為重要的是,它是完全自由的。
二、 Irrlicht特性
在深入分析API之前,請讓我更具體地介紹一下Irrlicht提供給了3D遊戲開發人員哪些功能:
·一個可以運行於Linux以及Windows 98,ME,NT,2000和XP(MacOS在計劃之中)等作業系統之上的引擎
·針對Direct3D 8產生器或Direct3D 9產生器(可選)提供了Anti-aliasing支援
·可換膚的GUI環境(包括一個很酷的具有金屬質地的帶陰影的皮膚),給一些老式的對話方塊加上漂亮的外觀
·情境管理系統,它允許無縫的室內/室外過渡
·角色動畫系統,帶有骨骼和變形目標動畫功能
·一個特殊的效果系統,包括粒子效果(雨,煙,火,雪,等等),告示板,燈光貼圖,環境,地圖,樣板緩衝區陰影,霧,紋理動畫,視差貼圖,凹凸貼圖,還有更多
·內建的材質支援,包括支援Pixel and Vertex Shaders版本1.1到3.0,ARB Fragment and Vertex程式以及HLSL(GLSL正在計劃中)
·.NET語言綁定,這使得引擎可用於所有的.NET語言例如C#,Visual Basic.NET以及Delphi.NET
·一內建的平台獨立的軟體產生器,特性有:z-緩衝,Gouraud陰影,alpha混合和透明性,還有快速的2D繪圖(見圖2)
·你久已期待的2D繪圖功能,例如alpha混合,基於關鍵色的位元影像複製,字型繪製,以及混合3D與2D圖形
·能直接匯入常見的建模檔案格式:Maya,3DStudio Max,COLLADA,DeleD,Milkshape,Quake 3 levels,Quake2 models,DirectX,Pulsar,My3DTools,FSRad以及Cartography Shop
·能直接從BMP,PNG,Photoshop,JPEG,Targa和PCX匯入紋理
·快速而易用的碰撞檢測與響應
·為快速的3D運算和容器模板庫進行了最佳化處理
·直接讀取檔案(可能是壓縮的,如.zip檔案)
·整合了快速的XML分析器
·為實現容易的本地化開發提供Unicode支援
圖2:基於Irrlicht的遊戲Yet Another Space Shooter(YASS),這裡顯示的是一個靜態遊戲幀中的令人吃驚的著色效果
三、 在Irrlicht中的特殊效果
在本文的例子中,我將向你展示怎樣使用樣板緩衝區影子技術,還有粒子系統,告示板,動態光以及水表面情境結點等技術。參見圖3。
Irrlicht引擎自動地檢查是否你的硬體支援模板緩衝;而如果不支援,則不啟動陰影。在這個示範程式中,在方法createDevice()中的’shadows’標誌被置位,以產生從一個動畫角色投下的動態影子。如果這個執行個體程式在你的PC上運行太慢,可以把這個標誌設定為false或者乾脆再買一塊更好些的圖形加速卡。
為能夠使用Irrlicht.DLL檔案,你需要連結到Irrlicht.lib庫檔案。你可以在工程設定對話方塊中設定這個選項;但是為了容易實現,你可以使用一個pragma先行編譯注釋命令。方法createDevice()負責執行個體化根對象-它使用引擎完成一切事情。參數如下:
·deviceType:裝置類型。當前你可選取Null裝置以及軟裝置,如DirectX8,DirectX9或OpenGL。
·windowSize:要建立的視窗的大小或全螢幕模式。這個例子中使用512x384。
·bits:每一像素位元數(當在全螢幕情況時)。僅允許值為16或者32。
·fullscreen:指定是否你想使裝置運行於全螢幕方式。
·stencilbuffer:指定是否你想使用樣板緩衝區以用於繪製陰影。
·vsync:指定是否你想啟動vsync(僅在全螢幕情況),可選。
·eventReceiver:一個接收事件的對象,可選。
為適合於本執行個體環境,你將裝載一個3D Studio Max檔案(一幢房子)。該房子看起來並沒有什麼特別的,但是Irrlicht引擎能為你建立一個相當酷的紋理貼圖。只需使用造型操縱器並為之建立一個planar紋理貼圖即可:
#include <irrlicht.h> #include <iostream> using namespace irr; #pragma comment(lib, "Irrlicht.lib") int main() { //讓我們假定使用者在本例中使用OpenGL //當然,也可以指定DirectX 8, 9, 等等. video::E_DRIVER_TYPE driverType = video::EDT_OPENGL; //建立裝置,如果建立失敗立即退出。 IrrlichtDevice *device = createDevice(driverType, core::dimension2d(640, 480), 16, false, true); if (device == 0) return 1; video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); |
我對從這個匯入檔案產生的發射光線顏色的效果並不滿意。下列代碼顯示怎樣實現這些步驟:
scene::IAnimatedMesh* mesh = smgr->getMesh("room.3ds"); smgr->getMeshManipulator()->makePlanarTextureMapping( mesh->getMesh(0), 0.008f); scene::ISceneNode* node = 0; node = smgr->addAnimatedMeshSceneNode(mesh); node->setMaterialTexture(0, driver->getTexture("wall.jpg")); node->getMaterial(0).EmissiveColor.set(0,0,0,0); |
四、 水動畫
你將添加的第一個特殊的效果是水動畫。為此,WaterSurfaceSceneNode匯入一個造型檔案並使之象水表面一樣地波動。如果你讓這個情境結點使用一種相當好的材質如MT_REFLECTION_2_LAYER,那麼它看起來相當酷:
mesh = smgr->addHillPlaneMesh("myHill", core::dimension2d(20,20), core::dimension2d(40,40), 0, 0, core::dimension2d(0,0), core::dimension2d(10,10)); node = smgr->addWaterSurfaceSceneNode(mesh->getMesh(0),3,300,30); node->setPosition(core::vector3df(0,7,0)); node->setMaterialTexture(0,driver->getTexture("water.jpg")); node->setMaterialTexture(1,driver->getTexture("stones.jpg")); node->setMaterialType(video::EMT_REFLECTION_2_LAYER); |
作為輸入造型,你可以建立一個陡峭的平面造型,但是你也可以為此使用任何其它的造型。你甚至能重用room.3ds輸入檔案(它看上去確實很奇怪)。該執行個體還用一個普通的石頭紋理模型來繪製所有另外的表面。
五、透明的告示板和燈光
第二個特殊的效果是很基本的但是非常有用:一個透明的告示板,伴之有一個動態燈光。為產生這種效果,你只需要產生一個燈光情境結點,並讓它四處飛行;而且,為了讓它看起來更酷一些,可以把一個告示板情境結點依附到它上面:
//建立燈光 node = smgr->addLightSceneNode(0, core::vector3df(0,0,0), video::SColorf(1.0f, 0.6f, 0.7f, 1.0f), 600.0f); scene::ISceneNodeAnimator* anim = 0; anim = smgr->createFlyCircleAnimator(core::vector3df(0,150,0),250.0f); node->addAnimator(anim); anim->drop(); // 把告示板依附到燈光 node = smgr->addBillboardSceneNode(node, core::dimension2d(50, 50)); node->setMaterialFlag(video::EMF_LIGHTING, false); node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); node->setMaterialTexture(0,driver->getTexture("particlewhite.bmp")); |
六、 粒子系統
下面介紹的這個特別效果更有趣:一個粒子系統。在Irrlicht引擎中,粒子系統既是組件化的,也是可擴充的,但是仍然便於使用。你只需要簡單地把粒子發射器放到一個粒子系統情境結點,這樣以來粒子看上去沒有產生源。這些發射器可以據需要進行靈活配置,並經常帶有許多參數,如粒子方向,粒子數量,以及粒子顏色等。
當然,發射器類型有區別(例如,一個點發射器能夠使粒子從一個固定的點上發出粒子)。如果該引擎提供的粒子發射器還不能滿足你的要求,你可以容易地建立你自己的發射器。這隻需簡單地從IParticleEmitter介面派生一個新類並使用setEmitter()方法把它依附到粒子系統上去即可。
下一個執行個體將建立一個盒子粒子發射器。你可能已經猜出,它從一個跳躍的盒中隨機產生粒子。由參數來定義盒子,粒子的方向,每秒產生粒子的最小和最大數目,顏色以及粒子的最小和最大生命週期。
一個完全由發射器組成的粒子系統將是令人生厭的,因為缺乏真實感。因此,Irrlicht支援粒子影響器-它負責在粒子到處飛揚時予以修整。一旦添加到粒子系統上,它們就能模仿另外的更真實的效果,象重力或風。在本例中的粒子影響器只是簡單地修改粒子的顏色來產生一種淡出效果。
可能你已經猜出,粒子影響器是通過派生IParticleAffector介面實現的,然後通過使用addAffector()方法把它添加到粒子系統上去。在你為該粒子系統設定了一種好看的材質後,你就有了一個看上去相當酷的野外宿營火的效果。通過調整材質,紋理,粒子發射器,還有影響器參數,你能容易地建立煙霧,下雨,爆炸,下雪等效果:
scene::IParticleSystemSceneNode* ps = 0; ps = smgr->addParticleSystemSceneNode(false); ps->setPosition(core::vector3df(-70,60,40)); ps->setScale(core::vector3df(2,2,2)); ps->setParticleSize(core::dimension2d(20.0f, 10.0f)); scene::IParticleEmitter* em = ps->createBoxEmitter( core::aabbox3d(-7,0,-7,7,1,7), core::vector3df(0.0f,0.03f,0.0f), 80,100, video::SColor(0,255,255,255), video::SColor(0,255,255,255), 800,2000); ps->setEmitter(em); em->drop(); scene::IParticleAffector* paf =ps->createFadeOutParticleAffector(); ps->addAffector(paf); paf->drop(); ps->setMaterialFlag(video::EMF_LIGHTING, false); ps->setMaterialTexture(0, driver->getTexture,"particle.bmp")); ps->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA); |
七、 影子投射
最後但也不容忽視一個問題是,你需要為一個動畫角色產生一個動態影子。為此,你裝載一個Quake2.md2模型檔案並把它放到你的world上去。為了建立影子,你只需要調用方法addShadowVolumeSceneNode()。你可能通過調用ISceneManager::setShadowColor()來控制影子的顏色;注意,這僅是全域可調整的,並影響所有的影子。好,下面就是你的產生動態影子效果的代碼:
mesh = smgr->getMesh("../../media/faerie.md2"); scene::IAnimatedMeshSceneNode* anode = 0; anode = smgr->addAnimatedMeshSceneNode(mesh); anode->setPosition(core::vector3df(-50,45,-60)); anode->setMD2Animation(scene::EMAT_STAND); anode->setMaterialTexture(0, driver->getTexture("../../media/Faerie5.BMP")); anode->addShadowVolumeSceneNode(); smgr->setShadowColor(video::SColor(220,0,0,0)); |
八、 遊戲迴圈
最後,你能進入由device->run()方法控制的遊戲迴圈。該迴圈將不斷運行,直到通過擷取一個關閉視窗事件(例如在Windows作業系統下的ALT-F4擊鍵)來退出裝置。你必須在一個beginScene()和endScene()命令對之間繪製每樣東西。beginScene()用指定的一種顏色清屏,如果需要的話,可以同時清除深度緩衝區。然後你就可以讓情境管理器和GUI環境來繪製它們的內容。隨著調用endScene(),每一樣東西都被繪製到螢幕上去。在本例中,你還可以動態地在標題列上顯示幀每秒(FPS)數,這對於嚴肅的遊戲開發人員是十分重要的事情:
scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); camera->setPosition(core::vector3df(-50,50,-150)); int lastFPS = -1; while(device->run()) { driver->beginScene(true, true, 0); smgr->drawAll(); driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Campfire FX example ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); |
結束迴圈後,你必須刪除先前用createDevice()方法建立的Irrlicht裝置。通過使用Irrlicht引擎,你應該刪除所有你用以’create’開頭的方法或函數建立的所有對象。你可以通過簡單地調用device->drop()來刪除該裝置對象。
九、你可能喜歡的Irrlicht外掛程式
正如在前面所介紹的,Irrlicht有一群勤奮的獨立程式開發人員並為之產生了大量的外掛程式,也用之開發了相當多的遊戲。這些開發人員中提出的許多的改進被再次整合到Irrlicht的隨後的發行版本中。下面我列舉其中的幾個例子,我想這會吸引許多頗有前程的開發人員感興趣:
·OCTTools,是一套用於Irrlicht的工具,由Murphy McCauley所建立,用於操作OCT檔案相關的:輸出器,載入器,甚至更多。
·ICE(Irrlicht通用引擎)是一個開發架構,它提供了一個工程的輪廓實現,從而加快了新工程的開發。
·MIM,由Murphy McCauley所建立,是一個非常有用的基於XML的檔案格式,可用於Irrlicht的載入器,轉換器及其各種工具。
·My3D是一個開發套件,它能夠使你把來自於各種3D包(3DStudio MAX,Giles,等等)中的燈光貼圖情境直接輸出到Irrlicht中。
·Dusty引擎允許程式員建立"任務"-這些"任務"可以完成程式員想做的任何事情。之後,這些任務被添加到一棵普通的任務樹上去,而每個任務可以有它們希望數目的孩子任務。任務"組"允許遊戲設計者在一棵完整的樹上執行普通的操作,例如暫停,繼續或破壞等。
·Irrlicht RPG(Erring Light)是一個3D 繞行走遊戲引擎,最初是針對RPG類遊戲開發的。
·2D 映像和精靈類組成了一個很有用的庫,它擴充了Irrlicht的2D能力。
·Zenprogramming網站,提供第一個針對Irrlicht的非正式的外部地形產生器,此處也提供很多相關的教程。