游戏引擎中多渲染器的设计于实现(2)
<strong><br/><br/></strong>游戏中的多渲染器的设计与实现 <p></p><p> 在了解了其他的引擎的实现方法后,我们可以开始自己写一个这样的框架了。(ps:不要把我写的代码给Hard core C++程序员看,这里暂时只关心原理)</p><p> 我现在正在写一个名为Uranus Halo的引擎(以下简称UHE),就以这个为例了。(ps:我用的编译器是VS2005。)</p><p> 先建立一个空解决方案,名为Uranus Halo Engine V0,添加工程:动态链接库工程,空项目, 取消“预编译头文件”,名为UHEMain,这是我们的引擎的主部分,是引擎的核心框架,也是多渲染器的入口。在这个工程中,添加新建项:<br/><br/><table cellspacing="1" cellpadding="4" width="80%" align="center"><tbody><tr><td class="code"><pre><br/> UHERenderDevice.h<br/> UHERenderer.h<br/> UHEPreriqusites.h<br/></pre></td></tr></tbody></table><br/></p><p> 其中,UHERenderDevice.h中定义了渲染器的纯基类,具体的内容如下:<br/><br/><table cellspacing="1" cellpadding="4" width="80%" align="center"><tbody><tr><td class="code"><pre><br/>//file: UHERenderDevice.h<br/>#ifndef _INCLUDE_UHERENDERDEVICE_H<br/>#define _INCLUDE_UHERENDERDEVICE_H<p></p><p>#include "UHEPrerequisites.h"<br/>#include "UHEBasicStruct.h"</p><p>namespace UHEngine<br/>{<br/> class _UHE_Export UHERenderDevice<br/> {<br/> public:<br/> UHERenderDevice(void){};<br/> virtual ~UHERenderDevice(void){};<br/><br/> virtual HRESULT Init( HWND hWnd, <br/> HINSTANCE hInst, <br/> bool bWindowed,<br/> DWORD dwWidth, <br/> DWORD dwHeight) = 0;<br/> virtual void ShutDown() = 0;<br/> virtual HRESULT Prepare() = 0;<br/> virtual bool IsRunning() = 0;<br/> virtual void SetClearColor( float fR, float fG, float fB ) = 0;<br/> virtual void Clear() = 0;<br/> virtual void Render() = 0;</p><p> //这里我省略了。。。。。。。<br/> };<br/>};<br/>#endif<br/></p></pre></td></tr></tbody></table><br/></p><p>注意到_UHE_Export这个宏,在UHEPreriqusites.h中有定义:<br/><br/><table cellspacing="1" cellpadding="4" width="80%" align="center"><tbody><tr><td class="code"><pre><br/>//file: UHEPrerequisites.h<br/>#ifndef _INCLUDE_UHEPREREQUISITES_H<br/>#define _INCLUDE_UHEPREREQUISITES_H<p></p><p>#include <windows.h><br/>#define _UHE_Export __declspec( dllexport )<br/>#endif<br/></p></pre></td></tr></tbody></table><br/></p><p>如果想导出某个类的成员函数到.dll文件,就需要在类名前加上&not; _UHE_Export 。</p><p>在UHERenderer.h中,我们定义了面向用户的类:<br/><br/><table cellspacing="1" cellpadding="4" width="80%" align="center"><tbody><tr><td class="code"><pre><br/>//file: UHERenderer.h<br/>#ifndef _INCLUDE_UHERENDERER_H<br/>#define _INCLUDE_UHERENDERER_H<p></p><p>#include "UHEPrerequisites.h"<br/>#include "UHERenderDevice.h"<br/>namespace UHEngine<br/>{<br/> class _UHE_Export UHERenderer<br/> {<br/> public:<br/> UHERenderer();<br/> ~UHERenderer();</p><p> void CreateDevice( int deviceType );<br/> UHERenderDevice *GetRenderDevice(){return this->m_pRenderDevice;}<br/> private:<br/> UHERenderDevice *m_pRenderDevice;<br/> HMODULE m_hDll; <br/> };<br/>};<br/>#endif<br/></p></pre></td></tr></tbody></table><br/></p><p> 注意,CreateDevice( int deviceType )这个函数是关键,我们先看一下它的实现,在UHERenderer.cpp中:<br/><br/><table cellspacing="1" cellpadding="4" width="80%" align="center"><tbody><tr><td class="code"><pre><br/>void UHERenderer::CreateDevice( int deviceType )<br/> {<br/> if( i )<br/> {<br/> this->m_hDll = LoadLibrary( "UHERenderDX9.dll" );<br/> }<br/> else<br/> {<br/> this->m_hDll = LoadLibrary( "UHERenderGL.dll" );<br/> }<br/> void (*pFun)(UHERenderDevice* &);<br/> pFun = (void (__cdecl *)(UHEngine::UHERenderDevice *&)) GetProcAddress( m_hDll, "dllCreate" );<br/> (*pFun)( this->m_pRenderDevice );<br/>}<br/></pre></td></tr></tbody></table><br/></p><p> 这里,我们规定当deviceType 大于0时,是使用的dx的渲染器,即加载的是 UHERenderDX9.dll。然后要注意这个"dllCreate"参数,这是从另一个工程中导出的.dll中的函数名,先放在这里,等一下在讨论。</p><p> 这样,UHEMain中的部分的框架就差不多了。我们先写一个dx9的渲染器的实现。</p><p> 建立新的项目,依然是.dll的空项目,没有预编译头文件。我们要先写一个dx的渲染器,继承于UHEMain中的渲染器纯虚类:<br/><br/><table cellspacing="1" cellpadding="4" width="80%" align="center"><tbody><tr><td class="code"><pre><br/>//file: UHERenderDX9.h<br/>#ifndef _INCLUDE_UHERENDERDX9_H<br/>#define _INCLUDE_UHERENDERDX9_H<p></p><p>#include "UHERenderDX9Base.h"</p><p>namespace UHEngine<br/>{<br/> class UHEDX9 : public UHERenderDevice<br/> {<br/> public:<br/> UHEDX9();<br/> UHEDX9( HWND hWnd, <br/> HINSTANCE hInst, <br/> bool bWindowed,<br/> DWORD dwWidth, <br/> DWORD dwHeight);<br/> ~UHEDX9();</p><p> HRESULT Init( HWND hWnd, <br/> HINSTANCE hInst, <br/> bool bWindowed,<br/> DWORD dwWidth, <br/> DWORD dwHeight);<br/> HRESULT Prepare();<br/> void ShutDown();</p><p> bool IsRunning(){ return m_bIsRunning; }<br/> void SetClearColor( float fR, float fG, float fB );<br/> void Clear();<br/> void Render();</p><p>
<br/> //这里我省略了。。。。。</p><p><br/> private:<br/> HRESULT BeginRendering( bool bClearPixel,<br/> bool bClearDepth,<br/> bool bClearStencil );<br/> HRESULT EndRendering();<br/> HRESULT Clear( bool bClearPixel,<br/> bool bClearDepth,<br/> bool bClearStencil );<br/> D3DXCOLOR m_clearColor;<br/> bool m_bIsRunning;<br/> bool m_bIsSceneRunning;<br/> bool m_bStencil;</p><p> HWND m_hWnd;<br/> HINSTANCE m_hInst;<br/> bool m_bWindowed;<br/> DWORD m_dwHeight;<br/> DWORD m_dwWidth;<br/>
<br/> LPDIRECT3D9 m_pDX9;<br/> LPDIRECT3DDEVICE9 m_pDevice;<br/> D3DPRESENT_PARAMETERS m_d3dpp;</p><p> //这里省略了。。。。。<br/> };<br/>};<br/>#endif<br/></p></pre></td></tr></tbody></table><br/></p><p> 完成这个类的实现。这样还不行,应为我们需要导出初始化基类渲染器的函数到UHERenderDX9.dll中。新建一个UHERenderDX9.def文件作为.dll的导出模块文件,文件中的内容如下:<br/><br/><table cellspacing="1" cellpadding="4" width="80%" align="center"><tbody><tr><td class="code"><pre><br/>LIBRARY "UHERenderDX9"<br/>EXPORTS<br/> dllCreate @1<br/> dllRelease @2<br/>;end of file<br/></pre></td></tr></tbody></table><br/></p><p>这样编译之后就可以将dllCreate和dllRelease函数导出到.dll中。<br/>dllCreate的定义:<br/><br/><table cellspacing="1" cellpadding="4" width="80%" align="center"><tbody><tr><td class="code"><pre><br/>//file : UHERenderDX9Dll.cpp<br/>#include "UHEDX9.h"<br/>#include "UHERenderer.h"<br/>namespace UHEngine <br/>{<br/> UHEDX9* pRenderDX9;<br/> extern "C" __declspec( dllexport ) void dllCreate( UHERenderDevice * &pRenderer )<br/> {<br/> pRenderDX9 = new UHEDX9();<br/> pRenderer = pRenderDX9;<br/> }<p></p><p> extern "C" __declspec( dllexport ) void dllRelease(void)<br/> {<br/> delete pRenderDX9;<br/> }<br/>}<br/></p></pre></td></tr></tbody></table><br/></p><p> 这样就可以了。</p><p>其他的问题:<br/> 关于.dll工程的问题,可以google一下相关的文章;关于项目的设置问题,我们这里没有讲到,可以编译一下,就可以发现相关的错误,再设置好路径和输出即可;这里只讲到了DX渲染器的实现,GL的方法一样,新建一个项目,然后实现。</p><p> 最后,我们再整理一下思路。在UEHMain中定义渲染的基类,和用户使用的类UHERenderer,在UHERenderDX9中写好DX版本的渲染器(即继承类),导出初始化函数(dllCreate)到.dll中,在UHERenderer中利用参数来判断该加载那个.dll,说穿了,本质就是判断,该调用哪个渲染器的构造函数,DX的还是GL的。。。</p><p> 这里的讨论只是框架上的实现,以后我会再写一些具体该注意的问题(也主要是框架和引擎的设计方面)。<br/></p>
页:
[1]