游戏开发论坛

 找回密码
 立即注册
搜索
查看: 8810|回复: 6

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

[复制链接]

22

主题

191

帖子

217

积分

中级会员

Rank: 3Rank: 3

积分
217
QQ
发表于 2006-6-9 14:29:00 | 显示全部楼层 |阅读模式
游戏中的多渲染器的设计与实现

  在了解了其他的引擎的实现方法后,我们可以开始自己写一个这样的框架了。(ps:不要把我写的代码给Hard core C++程序员看,这里暂时只关心原理)

  我现在正在写一个名为Uranus Halo的引擎(以下简称UHE),就以这个为例了。(ps:我用的编译器是VS2005。)

  先建立一个空解决方案,名为Uranus Halo Engine V0,添加工程:动态链接库工程,空项目, 取消“预编译头文件”,名为UHEMain,这是我们的引擎的主部分,是引擎的核心框架,也是多渲染器的入口。在这个工程中,添加新建项:

  1.         UHERenderDevice.h
  2.         UHERenderer.h
  3.         UHEPreriqusites.h
复制代码


  其中,UHERenderDevice.h中定义了渲染器的纯基类,具体的内容如下:

  1. //file: UHERenderDevice.h
  2. #ifndef _INCLUDE_UHERENDERDEVICE_H
  3. #define _INCLUDE_UHERENDERDEVICE_H

  4. #include "UHEPrerequisites.h"
  5. #include "UHEBasicStruct.h"

  6. namespace UHEngine
  7. {
  8.         class _UHE_Export UHERenderDevice
  9.         {
  10.         public:
  11.                 UHERenderDevice(void){};
  12.                 virtual ~UHERenderDevice(void){};
  13.                
  14.                 virtual HRESULT Init( HWND hWnd,
  15.                                 HINSTANCE hInst,
  16.                                 bool bWindowed,
  17.                                 DWORD dwWidth,
  18.                                 DWORD dwHeight) = 0;
  19.                 virtual void ShutDown() = 0;
  20.                 virtual HRESULT Prepare() = 0;
  21.                 virtual bool IsRunning() = 0;
  22.                 virtual void SetClearColor( float fR, float fG, float fB ) = 0;
  23.                 virtual void Clear() = 0;
  24.                 virtual void Render() = 0;

  25.                 //这里我省略了。。。。。。。
  26.         };
  27. };
  28. #endif
复制代码


注意到_UHE_Export这个宏,在UHEPreriqusites.h中有定义:

  1. //file: UHEPrerequisites.h
  2. #ifndef _INCLUDE_UHEPREREQUISITES_H
  3. #define _INCLUDE_UHEPREREQUISITES_H

  4. #include <windows.h>
  5. #define _UHE_Export __declspec( dllexport )
  6. #endif
复制代码


如果想导出某个类的成员函数到.dll文件,就需要在类名前加上¬ _UHE_Export 。

在UHERenderer.h中,我们定义了面向用户的类:

  1. //file: UHERenderer.h
  2. #ifndef _INCLUDE_UHERENDERER_H
  3. #define _INCLUDE_UHERENDERER_H

  4. #include "UHEPrerequisites.h"
  5. #include "UHERenderDevice.h"
  6. namespace UHEngine
  7. {
  8.         class _UHE_Export UHERenderer
  9.         {
  10.         public:
  11.                 UHERenderer();
  12.                 ~UHERenderer();

  13.                 void CreateDevice( int deviceType );
  14.                 UHERenderDevice *GetRenderDevice(){return this->m_pRenderDevice;}
  15.         private:
  16.                 UHERenderDevice *m_pRenderDevice;
  17.                 HMODULE m_hDll;
  18.         };
  19. };
  20. #endif
复制代码


  注意,CreateDevice( int deviceType )这个函数是关键,我们先看一下它的实现,在UHERenderer.cpp中:

  1. void UHERenderer::CreateDevice( int deviceType )
  2.         {
  3.                 if( i )
  4.                 {
  5.                         this->m_hDll = LoadLibrary( "UHERenderDX9.dll" );
  6.                 }
  7.                 else
  8.                 {
  9.                         this->m_hDll = LoadLibrary( "UHERenderGL.dll" );
  10.                 }
  11.                 void (*pFun)(UHERenderDevice* &);
  12.                 pFun = (void (__cdecl *)(UHEngine::UHERenderDevice *&)) GetProcAddress( m_hDll, "dllCreate" );
  13.                 (*pFun)( this->m_pRenderDevice );
  14. }
复制代码


  这里,我们规定当deviceType 大于0时,是使用的dx的渲染器,即加载的是 UHERenderDX9.dll。然后要注意这个"dllCreate"参数,这是从另一个工程中导出的.dll中的函数名,先放在这里,等一下在讨论。

  这样,UHEMain中的部分的框架就差不多了。我们先写一个dx9的渲染器的实现。

  建立新的项目,依然是.dll的空项目,没有预编译头文件。我们要先写一个dx的渲染器,继承于UHEMain中的渲染器纯虚类:

  1. //file: UHERenderDX9.h
  2. #ifndef _INCLUDE_UHERENDERDX9_H
  3. #define _INCLUDE_UHERENDERDX9_H

  4. #include "UHERenderDX9Base.h"

  5. namespace UHEngine
  6. {
  7.         class UHEDX9 : public UHERenderDevice
  8.         {
  9.         public:
  10.                 UHEDX9();
  11.                 UHEDX9( HWND hWnd,
  12.                                 HINSTANCE hInst,
  13.                                 bool bWindowed,
  14.                                 DWORD dwWidth,
  15.                                 DWORD dwHeight);
  16.                 ~UHEDX9();

  17.                 HRESULT Init( HWND hWnd,
  18.                                 HINSTANCE hInst,
  19.                                 bool bWindowed,
  20.                                 DWORD dwWidth,
  21.                                 DWORD dwHeight);
  22.                 HRESULT Prepare();
  23.                 void        ShutDown();

  24.                 bool        IsRunning(){ return m_bIsRunning; }
  25.                 void        SetClearColor( float fR, float fG, float fB );
  26.                 void        Clear();
  27.                 void        Render();

  28.                
  29.                 //这里我省略了。。。。。


  30.         private:
  31.                 HRESULT        BeginRendering( bool bClearPixel,
  32.                                                         bool bClearDepth,
  33.                                                         bool bClearStencil );
  34.                 HRESULT EndRendering();
  35.                 HRESULT Clear( bool bClearPixel,
  36.                                  bool bClearDepth,
  37.                                  bool bClearStencil );
  38.                 D3DXCOLOR                        m_clearColor;
  39.                 bool                                m_bIsRunning;
  40.                 bool                                m_bIsSceneRunning;
  41.                 bool                                m_bStencil;

  42.                 HWND                                m_hWnd;
  43.                 HINSTANCE                        m_hInst;
  44.                 bool                                m_bWindowed;
  45.                 DWORD                        m_dwHeight;
  46.                 DWORD                        m_dwWidth;
  47.                
  48.                 LPDIRECT3D9                        m_pDX9;
  49.                 LPDIRECT3DDEVICE9                m_pDevice;
  50.                 D3DPRESENT_PARAMETERS        m_d3dpp;

  51.                 //这里省略了。。。。。
  52.         };
  53. };
  54. #endif
复制代码


  完成这个类的实现。这样还不行,应为我们需要导出初始化基类渲染器的函数到UHERenderDX9.dll中。新建一个UHERenderDX9.def文件作为.dll的导出模块文件,文件中的内容如下:

  1. LIBRARY        "UHERenderDX9"
  2. EXPORTS
  3.         dllCreate @1
  4.         dllRelease @2
  5. ;end of file
复制代码


这样编译之后就可以将dllCreate和dllRelease函数导出到.dll中。
dllCreate的定义:

  1. //file : UHERenderDX9Dll.cpp
  2. #include "UHEDX9.h"
  3. #include "UHERenderer.h"
  4. namespace UHEngine
  5. {
  6.         UHEDX9* pRenderDX9;
  7.         extern "C" __declspec( dllexport ) void dllCreate( UHERenderDevice * &pRenderer )
  8.         {
  9.                 pRenderDX9 = new UHEDX9();
  10.                 pRenderer = pRenderDX9;
  11.         }

  12.         extern "C" __declspec( dllexport ) void dllRelease(void)
  13.         {
  14.                 delete pRenderDX9;
  15.         }
  16. }
复制代码


  这样就可以了。

其他的问题:
  关于.dll工程的问题,可以google一下相关的文章;关于项目的设置问题,我们这里没有讲到,可以编译一下,就可以发现相关的错误,再设置好路径和输出即可;这里只讲到了DX渲染器的实现,GL的方法一样,新建一个项目,然后实现。

  最后,我们再整理一下思路。在UEHMain中定义渲染的基类,和用户使用的类UHERenderer,在UHERenderDX9中写好DX版本的渲染器(即继承类),导出初始化函数(dllCreate)到.dll中,在UHERenderer中利用参数来判断该加载那个.dll,说穿了,本质就是判断,该调用哪个渲染器的构造函数,DX的还是GL的。。。

  这里的讨论只是框架上的实现,以后我会再写一些具体该注意的问题(也主要是框架和引擎的设计方面)。

22

主题

191

帖子

217

积分

中级会员

Rank: 3Rank: 3

积分
217
QQ
 楼主| 发表于 2006-6-9 14:47:00 | 显示全部楼层

Re:游戏引擎中多渲染器的设计于实现(2)

格式没有经过调整(这里好像不能从word粘贴的),
大家可以看我的原文:
http://blog.csdn.net/xjyhust/archive/2006/06/09/782873.aspx

30

主题

357

帖子

388

积分

中级会员

Rank: 3Rank: 3

积分
388
QQ
发表于 2006-6-10 23:41:00 | 显示全部楼层

Re:游戏引擎中多渲染器的设计于实现(2)

问个比较弱智的问题。。动态连接库比静态的好在哪啊?

121

主题

2029

帖子

2034

积分

金牌会员

Rank: 6Rank: 6

积分
2034
QQ
发表于 2006-6-11 10:51:00 | 显示全部楼层

Re:游戏引擎中多渲染器的设计于实现(2)

ExportClass用的还是不爽。不如用Factory或者COM。

22

主题

191

帖子

217

积分

中级会员

Rank: 3Rank: 3

积分
217
QQ
 楼主| 发表于 2006-6-11 11:42:00 | 显示全部楼层

Re:游戏引擎中多渲染器的设计于实现(2)

动态链接库编译的代码小,可以给多个程序公用,在内存里面只有一个副本。

恩,ExportClass是比较傻的办法,这里也是想尽量少用这种方法。

18

主题

971

帖子

982

积分

高级会员

Rank: 4

积分
982
发表于 2006-6-15 16:22:00 | 显示全部楼层

Re:游戏引擎中多渲染器的设计于实现(2)

代码有点乱。。

48

主题

155

帖子

265

积分

中级会员

Rank: 3Rank: 3

积分
265
发表于 2006-6-17 10:06:00 | 显示全部楼层

Re:游戏引擎中多渲染器的设计于实现(2)

ExportClass

如果我想用户继承我的类,是不是只有使用ExportClass
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-24 18:05

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表