圖1.Irrlicht 3D引擎 |
Irrlicht是一個德國神話故事中的一種動物的名字,它能夠發光和飛翔,可以在大部分的沼澤地附近發現它。單詞"Irrlicht"是兩個德國單詞("irr"意思是瘋狂的;而"Licht"意思是光)的組合。在英語中,它被譯爲"鬼火"。
Irrlicht十分幸運地爲一個巨大的活躍的開發團隊以大量的工程所支持。然而,因爲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。
圖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的非正式的外部地形生成器,此處也提供很多相關的教程。