Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 游戏天堂 > 游戏开发 > 游戏引擎中的多渲染器的设计与实现(1)
【标  题】:游戏引擎中的多渲染器的设计与实现(1)
【关键字】:
【来  源】:http://blog.csdn.net/xjyhust/archive/2006/06/06/775286.aspx

游戏引擎中的多渲染器的设计与实现(1)

Your Ad Here

游戏引擎中的多渲染器的设计与实现(1

很多游戏引擎都提供了多种渲染器(DirectXOpenGLSoftware),甚至是多种平台(WindowsLinuxMac),这对于引擎的设计和实现来说是一个很大的挑战,尤其是多渲染器,又要考虑到效率,又要考虑到通用,又要发挥每种渲染器的特点,这的确是一道天堑。这里讨论的原则很简单: 1. Keep it simple; 2. Make it work first.

先看一下Ogre使用的方法。Ogre中各个模块是使用的插件式的设计“组合”在一起的,你可以在Ogre的基础上加入你自己写的渲染器,而不需要开动其他的代码(甚至是OgreMain引擎的主体部分的代码)。有很多的软件的架构都采用的类似的插件,最有名的像IDE Eclipse, 引擎有如Unreal 2 Unreal 3等。写一个渲染器的插件并不很难,但是设计非插件的引擎内核是十分困难的。如果引擎的内核在初期没有设计好,在后期没有办法进行过多的修改;当然,如果设计得很好,那么对引擎进行功能的扩充或修改将是非常方便的(Unreal 2 就是使用了插件式的设计,在开发到中期后改掉了原来自己开发的物理模块,而是使用了Novodex)。

另外一种方法是将渲染器的种类作为引擎的主模块构造函数(或者相关的初始化功能的函数)的参数。比如Irrilicht中就是用的这种方法,Irrilicht中,有一个CVideoNull纯虚类,不同的渲染器都继承于这个类;引擎的主模块有一个类CIrrDeviceWin32,其构造函数为:

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);

 

其中E_DRIVER_TYPE为枚举类型,用来表示渲染器的类型。然后在构造函数的实现中,用switch来进行初始化基类渲染器。这种方法的缺点是,引擎框架在物理上,逻辑上存在循环依赖(这里指的是代码层面,也即编译层面上的依赖关系),主引擎部分依赖于各个渲染器,而各个渲染器又依赖于主引擎的其他部分。在编译时,这种设计的代价是巨大的。

使用动态链接库是解决这个问题的方法之一,同时这也是插件式设计的实现手段(在linux中,有相应的机制shared object,由于我之前没有接触过linux上的编程,所以这里的讨论仅限于windows平台)。将原来的主引擎的构造函数中的代码改一下,依然还是用switch进行不同的渲染器的选择,只不过是调用不同的.dll来进行基类函数的构造。比如在ogre中,每一个渲染器都有一个导出到.dll的模块定义文件(.def文件),比如directx的渲染器中的.def文件的定义如下:

LIBRARY RenderSystem_Direct3D9

EXPORTS 

                   dllStartPlugin @1

              dllStopPlugin  @2

其中dllStartPlugindllStopPlugin 分别是创建和析构渲染器的函数,具体的定义为:

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;

     }

}

其中Root::getSingleton().addRenderSystem( d3dRendPlugin )就是将生成的渲染器作为插件,“插”到主引擎中。在主引擎中,对应的部分为:

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();

              }

         }

     }

这样就完成了Root::getSingleton().addRenderSystem( d3dRendPlugin )

 

Projective Texture的原理与实现:【上一篇】
(原创)CE MAPI实例讲解 --- 如何设置收件人信息(五):【下一篇】
【相关文章】
没有相关文章
【随机文章】
  • 网页排版CSS教学第四章 颜色背景的CSS
  • 通用权限管理控件
  • 抨击世俗:如何扭转一下拜年的风向和风气[转载]
  • 用VB编写标准CGI程序
  • 让两个并列的不换行的方式
  • 加密算法之DSA算法
  • P&P OB CAB EntLib
  • 限制Win9x、NT系统功能二十八招
  • FSO总结
  • 10年回顾:世界各地开发高手谈Java (3)
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 软讯网络 All Rigths Reserved.