暴米花 发表于 2006-12-7 10:25:00

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

<strong><br/><br/></strong>游戏中的多渲染器的设计与实现 <p></p><p>  在了解了其他的引擎的实现方法后,我们可以开始自己写一个这样的框架了。(ps:不要把我写的代码给Hard&nbsp;core&nbsp;C++程序员看,这里暂时只关心原理)</p><p>  我现在正在写一个名为Uranus&nbsp;Halo的引擎(以下简称UHE),就以这个为例了。(ps:我用的编译器是VS2005。)</p><p>  先建立一个空解决方案,名为Uranus&nbsp;Halo&nbsp;Engine&nbsp;V0,添加工程:动态链接库工程,空项目,&nbsp;取消“预编译头文件”,名为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:&nbsp;UHERenderDevice.h<br/>#ifndef&nbsp;_INCLUDE_UHERENDERDEVICE_H<br/>#define&nbsp;_INCLUDE_UHERENDERDEVICE_H<p></p><p>#include&nbsp;"UHEPrerequisites.h"<br/>#include&nbsp;"UHEBasicStruct.h"</p><p>namespace&nbsp;UHEngine<br/>{<br/>        class&nbsp;_UHE_Export&nbsp;UHERenderDevice<br/>        {<br/>        public:<br/>                UHERenderDevice(void){};<br/>                virtual&nbsp;~UHERenderDevice(void){};<br/>
                                                                <br/>                virtual&nbsp;HRESULT&nbsp;Init(&nbsp;HWND&nbsp;hWnd,&nbsp;<br/>                                HINSTANCE&nbsp;hInst,&nbsp;<br/>                                bool&nbsp;bWindowed,<br/>                                DWORD&nbsp;dwWidth,&nbsp;<br/>                                DWORD&nbsp;dwHeight)&nbsp;=&nbsp;0;<br/>                virtual&nbsp;void&nbsp;ShutDown()&nbsp;=&nbsp;0;<br/>                virtual&nbsp;HRESULT&nbsp;Prepare()&nbsp;=&nbsp;0;<br/>                virtual&nbsp;bool&nbsp;IsRunning()&nbsp;=&nbsp;0;<br/>                virtual&nbsp;void&nbsp;SetClearColor(&nbsp;float&nbsp;fR,&nbsp;float&nbsp;fG,&nbsp;float&nbsp;fB&nbsp;)&nbsp;=&nbsp;0;<br/>                virtual&nbsp;void&nbsp;Clear()&nbsp;=&nbsp;0;<br/>                virtual&nbsp;void&nbsp;Render()&nbsp;=&nbsp;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:&nbsp;UHEPrerequisites.h<br/>#ifndef&nbsp;_INCLUDE_UHEPREREQUISITES_H<br/>#define&nbsp;_INCLUDE_UHEPREREQUISITES_H<p></p><p>#include&nbsp;&lt;windows.h&gt;<br/>#define&nbsp;_UHE_Export&nbsp;__declspec(&nbsp;dllexport&nbsp;)<br/>#endif<br/></p></pre></td></tr></tbody></table><br/></p><p>如果想导出某个类的成员函数到.dll文件,就需要在类名前加上&amp;not;&nbsp;_UHE_Export&nbsp;。</p><p>在UHERenderer.h中,我们定义了面向用户的类:<br/><br/><table cellspacing="1" cellpadding="4" width="80%" align="center"><tbody><tr><td class="code"><pre><br/>//file:&nbsp;UHERenderer.h<br/>#ifndef&nbsp;_INCLUDE_UHERENDERER_H<br/>#define&nbsp;_INCLUDE_UHERENDERER_H<p></p><p>#include&nbsp;"UHEPrerequisites.h"<br/>#include&nbsp;"UHERenderDevice.h"<br/>namespace&nbsp;UHEngine<br/>{<br/>        class&nbsp;_UHE_Export&nbsp;UHERenderer<br/>        {<br/>        public:<br/>                UHERenderer();<br/>                ~UHERenderer();</p><p>                void&nbsp;CreateDevice(&nbsp;int&nbsp;deviceType&nbsp;);<br/>                UHERenderDevice&nbsp;*GetRenderDevice(){return&nbsp;this-&gt;m_pRenderDevice;}<br/>        private:<br/>                UHERenderDevice&nbsp;*m_pRenderDevice;<br/>                HMODULE&nbsp;m_hDll;&nbsp;<br/>        };<br/>};<br/>#endif<br/></p></pre></td></tr></tbody></table><br/></p><p>  注意,CreateDevice(&nbsp;int&nbsp;deviceType&nbsp;)这个函数是关键,我们先看一下它的实现,在UHERenderer.cpp中:<br/><br/><table cellspacing="1" cellpadding="4" width="80%" align="center"><tbody><tr><td class="code"><pre><br/>void&nbsp;UHERenderer::CreateDevice(&nbsp;int&nbsp;deviceType&nbsp;)<br/>        {<br/>                if(&nbsp;i&nbsp;)<br/>                {<br/>                        this-&gt;m_hDll&nbsp;=&nbsp;LoadLibrary(&nbsp;"UHERenderDX9.dll"&nbsp;);<br/>                }<br/>                else<br/>                {<br/>                        this-&gt;m_hDll&nbsp;=&nbsp;LoadLibrary(&nbsp;"UHERenderGL.dll"&nbsp;);<br/>                }<br/>                void&nbsp;(*pFun)(UHERenderDevice*&nbsp;&amp;);<br/>                pFun&nbsp;=&nbsp;(void&nbsp;(__cdecl&nbsp;*)(UHEngine::UHERenderDevice&nbsp;*&amp;))&nbsp;GetProcAddress(&nbsp;m_hDll,&nbsp;"dllCreate"&nbsp;);<br/>                (*pFun)(&nbsp;this-&gt;m_pRenderDevice&nbsp;);<br/>}<br/></pre></td></tr></tbody></table><br/></p><p>  这里,我们规定当deviceType&nbsp;大于0时,是使用的dx的渲染器,即加载的是&nbsp;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:&nbsp;UHERenderDX9.h<br/>#ifndef&nbsp;_INCLUDE_UHERENDERDX9_H<br/>#define&nbsp;_INCLUDE_UHERENDERDX9_H<p></p><p>#include&nbsp;"UHERenderDX9Base.h"</p><p>namespace&nbsp;UHEngine<br/>{<br/>        class&nbsp;UHEDX9&nbsp;:&nbsp;public&nbsp;UHERenderDevice<br/>        {<br/>        public:<br/>                UHEDX9();<br/>                UHEDX9(&nbsp;HWND&nbsp;hWnd,&nbsp;<br/>                                HINSTANCE&nbsp;hInst,&nbsp;<br/>                                bool&nbsp;bWindowed,<br/>                                DWORD&nbsp;dwWidth,&nbsp;<br/>                                DWORD&nbsp;dwHeight);<br/>                ~UHEDX9();</p><p>                HRESULT&nbsp;Init(&nbsp;HWND&nbsp;hWnd,&nbsp;<br/>                                HINSTANCE&nbsp;hInst,&nbsp;<br/>                                bool&nbsp;bWindowed,<br/>                                DWORD&nbsp;dwWidth,&nbsp;<br/>                                DWORD&nbsp;dwHeight);<br/>                HRESULT&nbsp;Prepare();<br/>                void        ShutDown();</p><p>                bool        IsRunning(){&nbsp;return&nbsp;m_bIsRunning;&nbsp;}<br/>                void        SetClearColor(&nbsp;float&nbsp;fR,&nbsp;float&nbsp;fG,&nbsp;float&nbsp;fB&nbsp;);<br/>                void        Clear();<br/>                void        Render();</p><p>
                                                                <br/>                //这里我省略了。。。。。</p><p><br/>        private:<br/>                HRESULT        BeginRendering(&nbsp;bool&nbsp;bClearPixel,<br/>                                                        bool&nbsp;bClearDepth,<br/>                                                        bool&nbsp;bClearStencil&nbsp;);<br/>                HRESULT&nbsp;EndRendering();<br/>                HRESULT&nbsp;Clear(&nbsp;bool&nbsp;bClearPixel,<br/>                                &nbsp;bool&nbsp;bClearDepth,<br/>                                &nbsp;bool&nbsp;bClearStencil&nbsp;);<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&nbsp;@1<br/>        dllRelease&nbsp;@2<br/>;end&nbsp;of&nbsp;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&nbsp;:&nbsp;UHERenderDX9Dll.cpp<br/>#include&nbsp;"UHEDX9.h"<br/>#include&nbsp;"UHERenderer.h"<br/>namespace&nbsp;UHEngine&nbsp;<br/>{<br/>        UHEDX9*&nbsp;pRenderDX9;<br/>        extern&nbsp;"C"&nbsp;__declspec(&nbsp;dllexport&nbsp;)&nbsp;void&nbsp;dllCreate(&nbsp;UHERenderDevice&nbsp;*&nbsp;&amp;pRenderer&nbsp;)<br/>        {<br/>                pRenderDX9&nbsp;=&nbsp;new&nbsp;UHEDX9();<br/>                pRenderer&nbsp;=&nbsp;pRenderDX9;<br/>        }<p></p><p>        extern&nbsp;"C"&nbsp;__declspec(&nbsp;dllexport&nbsp;)&nbsp;void&nbsp;dllRelease(void)<br/>        {<br/>                delete&nbsp;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]
查看完整版本: 游戏引擎中多渲染器的设计于实现(2)