CIrrDeviceWin32(video::E_DRIVER_TYPE deviceType,
const core::dimension2d<s32>& windowSize, u32 bits,
bool fullscreen, bool stencilbuffer, bool vsync, IEventReceiver* receiver,
const wchar_t* version);
[/code] 其中E_DRIVER_TYPE为枚举类型,用来表示渲染器的类型。然后在构造函数的实现中,用switch来进行初始化基类渲染器。这种方法的缺点是,引擎框架在物理上,逻辑上存在循环依赖(这里指的是代码层面,也即编译层面上的依赖关系),主引擎部分依赖于各个渲染器,而各个渲染器又依赖于主引擎的其他部分。在编译时,这种设计的代价是巨大的。
使用动态链接库是解决这个问题的方法之一,同时这也是插件式设计的实现手段(在linux中,有相应的机制shared object,由于我之前没有接触过linux上的编程,所以这里的讨论仅限于windows平台)。将原来的主引擎的构造函数中的代码改一下,依然还是用switch进行不同的渲染器的选择,只不过是调用不同的.dll来进行基类函数的构造。比如在ogre中,每一个渲染器都有一个导出到.dll的模块定义文件(.def文件),比如directx的渲染器中的.def文件的定义如下:
[code]
LIBRARY RenderSystem_Direct3D9
EXPORTS
dllStartPlugin @1
dllStopPlugin @2
[/code]
其中dllStartPlugin和dllStopPlugin 分别是创建和析构渲染器的函数,具体的定义为:
[code]
namespace Ogre
{
D3D9RenderSystem* d3dRendPlugin;
D3D9HLSLProgramFactory* hlslProgramFactory;
extern "C" void dllStartPlugin(void) throw()
{
// Create the DirectX 8 rendering api
HINSTANCE hInst = GetModuleHandle( "RenderSystem_Direct3D9.dll" );
d3dRendPlugin = new D3D9RenderSystem( hInst );
// Register the render system
Root::getSingleton().addRenderSystem( d3dRendPlugin );
// create & register HLSL factory
hlslProgramFactory = new D3D9HLSLProgramFactory();
HighLevelGpuProgramManager::getSingleton().addFactory(hlslProgramFactory);
}
extern "C" void dllStopPlugin(void)
{
delete d3dRendPlugin;
delete hlslProgramFactory;
}
}
[/code]
其中Root::getSingleton().addRenderSystem( d3dRendPlugin )就是将生成的渲染器作为插件,“插”到主引擎中。在主引擎中,对应的部分为:
[code]
void Root::loadPlugin(const String& pluginName)
{
// Load plugin library
DynLib* lib = DynLibManager::getSingleton().load( pluginName );
// Store for later unload
mPluginLibs.push_back(lib);
// Call startup function
DLL_START_PLUGIN pFunc = (DLL_START_PLUGIN)lib->getSymbol("dllStartPlugin");
if (!pFunc)
OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Cannot find symbol dllStartPlugin in library " + pluginName,
"Root::loadPlugins");
pFunc();
if (mIsInitialised)
{
// initialise too
DLL_INIT_PLUGIN pFunc = (DLL_INIT_PLUGIN)lib->getSymbol("dllInitialisePlugin");
if (pFunc)
{
pFunc();
}
}
}