本文共 4847 字,大约阅读时间需要 16 分钟。
理清一个引擎,不得不先理清它的层次结构,进而理清渲染流程。 本文给出了鬼火引擎中的设备抽象层,有助于对鬼火引擎源码的快速阅读。
IrrlichtDevice *device =
createDevice(driverType, core::dimension2d<u32>(640, 480), 16, false, shadows); 这个函数大家都很熟悉,那闲话不多说,我们就从这里开始。。。 IrrlichtDevice 设备的顶层接口 CIrrDeviceStub 实现设备顶层接口类,所有设备都从此派生,这里的设备是指和平台相关的设备 类成员: video::IVideoDriver* VideoDriver;// 图形接口 gui::IGUIEnvironment* GUIEnvironment;// GUI接口 scene::ISceneManager* SceneManager;//场景节点接口 ITimer* Timer; //定时器,保证了一个设备持有一个定时器 gui::ICursorControl* CursorControl; //鼠标控制器 IEventReceiver* UserReceiver;//事件处理器 CLogger* Logger;//日志 IOSOperator* Operator; //系统操作相关 io::IFileSystem* FileSystem; //文件系统 scene::ISceneManager* InputReceivingSceneManager; // video::CVideoModeList VideoModeList; //图形模式列表 SIrrlichtCreationParameters CreationParams;//创建图形设备时的参数 SMouseMultiClicks MouseMultiClicks; //鼠标多击(比双击还多) 从以上类成员就可以看出设备里面包含些什么 下面是针对各种不同平台的实现类 CIrrDeviceConsole CIrrDeviceLinux CIrrDeviceSDL CIrrDeviceWin32 从类名可以看出是针对哪个平台的。CIrrDeviceConsole是控制台 上面几个平台的实现还除了派生于CIrrDeviceStub外,还派生于IImagePresenter IImagePresenter只有一个函数 //! presents a surface in the client area virtual bool present(video::IImage* surface, void* windowId=0, core::rect<s32>* src=0 ) = 0; 输出到目标客户区。。。 对于平台相关的设备的实现,拿WIN32的来说 下面是类成员: core::position2d<s32> CursorPos; core::dimension2d<u32> WindowSize; core::dimension2d<f32> InvWindowSize; bool IsVisible; HWND HWnd; s32 BorderX, BorderY; bool UseReferenceRect; core::rect<s32> ReferenceRect; 可以看出,即是持有与平台相关的数据。平台无关的都被CIrrDeviceStub搞定啦 下面我们来仔细看看createDevice函数做了些什么。 用法示例: IrrlichtDevice *device = createDevice(driverType, core::dimension2d<u32>(640, 480), 16, false, shadows); createDevice函数的参数意思就不多说了,会用API的人都知道。 实现如下: IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDevice(video::E_DRIVER_TYPE driverType, const core::dimension2d<u32>& windowSize, u32 bits, bool fullscreen, bool stencilbuffer, bool vsync, IEventReceiver* res) { SIrrlichtCreationParameters p; p.DriverType = driverType; p.WindowSize = windowSize; p.Bits = (u8)bits; p.Fullscreen = fullscreen; p.Stencilbuffer = stencilbuffer; p.Vsync = vsync; p.EventReceiver = res; return createDeviceEx(p); } 可以看出,它将参数赋值给SIrrlichtCreationParameters结构,然后调用createDeviceEx 关键就是这个createDeviceEx,实现了对应平台的创建 主要代码如下 IrrlichtDevice* dev = 0; #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ if (params.DeviceType == EIDT_WIN32 || (!dev && params.DeviceType == EIDT_BEST)) dev = new CIrrDeviceWin32(params); #endif #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ if (params.DeviceType == EIDT_OSX || (!dev && params.DeviceType == EIDT_BEST)) dev = new CIrrDeviceMacOSX(params); #endif #ifdef _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ if (params.DeviceType == EIDT_WINCE || (!dev && params.DeviceType == EIDT_BEST)) dev = new CIrrDeviceWinCE(params); #endif #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ if (params.DeviceType == EIDT_X11 || (!dev && params.DeviceType == EIDT_BEST)) dev = new CIrrDeviceLinux(params); #endif #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ if (params.DeviceType == EIDT_SDL || (!dev && params.DeviceType == EIDT_BEST)) dev = new CIrrDeviceSDL(params); #endif #ifdef _IRR_COMPILE_WITH_CONSOLE_DEVICE_ if (params.DeviceType == EIDT_CONSOLE || (!dev && params.DeviceType == EIDT_BEST)) dev = new CIrrDeviceConsole(params); #endif 根据宏定义决定了平台相关系,从而创建出相应的平台。。。。。 请大家注意上面代码中的params参数,他就是一个SIrrlichtCreationParameters结构体,这个参数决定了创建图形设备的信息。我们以WIN32为例,来继续探究IRR是如何实现平台、图形API无关的。 CIrrDeviceWin32(const SIrrlichtCreationParameters& params); 这是CIrrDeviceWin32它的构造函数,从而可知,params决定了一切,而params除了包含用户指定的API信息以外,并未有平台相关的信息,所以,平台创建是无关的,而params决定了图形API的选择,当然,图形API的选择也可以通过类似的方案来实现,比如:在用户创建设备(调用createDevice)前,可以先测试是否支持D3D,如果不是再选择OPEGNL。。。。 扯远了,继续说一下是怎么创建的。。 下面我们进入他的构造函数的实现 构造函数将params传给了他的父类。。。。,而它自已实现了WINDOWS相关的创建工作,如窗口类注册,创建等。。。 params在父类中由CreationParams;//保存(如果忘了,请看贴子开头的地方)。。。 构造函数还调用了另一个函数(当然不止一个,我只是说,这是一个与CreationParams相关的函数) 好了,就是它:createDriver();这个函数实现的代码大致如下 void CIrrDeviceWin32::createDriver() { switch(CreationParams.DriverType) { case video::EDT_DIRECT3D8: #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ VideoDriver = video::createDirectX8Driver break; case video::EDT_DIRECT3D9: #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ VideoDriver = video::createDirectX9Driver break; case video::EDT_OPENGL: #ifdef _IRR_COMPILE_WITH_OPENGL_ VideoDriver = video::createOpenGLDriver(CreationParams, FileSystem, this); break; case video::EDT_SOFTWARE: #ifdef _IRR_COMPILE_WITH_SOFTWARE_ VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize, break; case video::EDT_BURNINGSVIDEO: #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ VideoDriver = video::createSoftwareDriver2 break; case video::EDT_NULL: // create null driver VideoDriver = video::createNullDriver break; } } 一切都明了了…… 这里并没有作详细的研究,只是一个简单的介绍,算是一个导读吧。大家根据这个思路去读源码,相信很快就能研究明白了~~~作者:
出处: 蛮牛专栏: 简介:09年入行,喜欢游戏和编程,对3D游戏和引擎尤其感兴趣。 版权声明:本文版权归作者和博客园共有,欢迎转载。转载必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。转载:http://www.cnblogs.com/geniusalex/archive/2010/04/26/1940509.html