zoukankan      html  css  js  c++  java
  • 13. GameProjec1_GameEngine

    工程GameProject1: main.h, main.cpp这两个文件用于创建游戏Stranded。

    工程GameEngine:RenderInterface.h , D3DRenderer.h, D3DRenderer.cpp, engine.h, defines.h.  D3DRenderer.h和D3DRenderer.cpp用于创建Direct3D渲染系统; RenderInterface.h文件是一个基类,D3DRenderer就是从该类派生出来的;engine.h和defines.h包含了游戏引擎中要用到的Define(定义)、Function Prototype(函数原型)、Enumeration(枚举)、Structure(结构)和Include(包含)等语句。

    main.h

    #ifndef _UGP_MAIN_H_
    #define _UGP_MAIN_H_


    #include
    "StrandedEngine/engine.h"
    #pragma comment(lib, "lib/StrandedEngine.lib")

    #define WINDOW_CLASS "StrandedGame"
    #define WINDOW_NAME "Stranded"
    #define WIN_WIDTH 800
    #define WIN_HEIGHT 600
    #define FULLSCREEN 1

    // Function Prototypes...
    bool InitializeEngine();
    void ShutdownEngine();

    // Main game functions.
    bool GameInitialize();
    void GameLoop();
    void GameShutdown();

    #endif

      main.cpp

    #include"main.h"


    // Globals...
    HWND g_hwnd;
    CRenderInterface
    *g_Render = NULL;


    LRESULT WINAPI MsgProc(HWND hd, UINT msg, WPARAM wp, LPARAM lp)
    {
    switch(msg)
    {
    case WM_DESTROY:
    PostQuitMessage(
    0);
    return 0;
    break;

    case WM_KEYUP:
    if(wp == VK_ESCAPE) PostQuitMessage(0);
    break;
    }

    return DefWindowProc(hd, msg, wp, lp);
    }


    int WINAPI WinMain(HINSTANCE h, HINSTANCE p, LPSTR cmd, int show)
    {
    // Register the window class
    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc,
    0L, 0L, GetModuleHandle(NULL), NULL, NULL,
    NULL, NULL, WINDOW_CLASS, NULL };
    RegisterClassEx(
    &wc);

    // Create the application's window
    if(FULLSCREEN)
    {
    g_hwnd
    = CreateWindowEx(NULL, WINDOW_CLASS, WINDOW_NAME,
    WS_POPUP
    | WS_SYSMENU | WS_VISIBLE, 0, 0,
    WIN_WIDTH, WIN_HEIGHT,
    NULL, NULL, h, NULL);
    }
    else
    {
    g_hwnd
    = CreateWindowEx(NULL, WINDOW_CLASS, WINDOW_NAME,
    WS_OVERLAPPEDWINDOW
    | WS_VISIBLE, 0,
    0, WIN_WIDTH, WIN_HEIGHT,
    NULL, NULL, h, NULL);
    }

    if(g_hwnd)
    {
    // Show the window
    ShowWindow(g_hwnd, SW_SHOWDEFAULT);
    UpdateWindow(g_hwnd);
    }

    // Initialize the Stranded Engine.
    if(InitializeEngine())
    {
    // Initialize Stranded game.
    if(GameInitialize())
    {
    // Enter the message loop
    MSG msg;
    ZeroMemory(
    &msg, sizeof(msg));

    SetCursorPos(
    0, 0);

    while(msg.message != WM_QUIT)
    {
    if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
    {
    TranslateMessage(
    &msg);
    DispatchMessage(
    &msg);
    }
    else
    GameLoop();
    }
    }
    }

    // Release any and all resources.
    GameShutdown();
    ShutdownEngine();

    UnregisterClass(WINDOW_CLASS, wc.hInstance);
    return 0;
    }


    bool InitializeEngine()
    {
    if(!CreateD3DRenderer(&g_Render)) return false;

    if(!g_Render->Initialize(WIN_WIDTH, WIN_HEIGHT,
    g_hwnd, FULLSCREEN))
    return false;

    g_Render
    ->SetClearCol(0, 0, 0);

    return true;
    }


    void ShutdownEngine()
    {
    if(g_Render)
    {
    g_Render
    ->Shutdown();
    delete g_Render;
    g_Render
    = NULL;
    }
    }


    bool GameInitialize()
    {
    return true;
    }


    void GameLoop()
    {
    if(!g_Render) return;

    g_Render
    ->StartRender(1, 1, 0);

    g_Render
    ->EndRendering();
    }


    void GameShutdown()
    {

    }

    InitializeEngine()函数调用CreateD3DRenderer()函数为渲染系统分配内存。该函数调用对象的Initialize()函数初始化渲染系统。它将清除色设为黑色。清除色就是在应用程序启动新帧时,清除后台缓存用的颜色。ShutdownEngine()函数只是简单地将所有系统使用的动态内存清除干净。到目前为止,只有一个基本的渲染系统,所以这就是要清除的全部内容。GameInitialize()和GameShutdown()这两个函数都是空的,因为在此还没有创建具体的游戏代码。GameLoop()函数和第1章的render()函数很类似。该函数只是完成渲染一个黑屏的基本功能。

      

    defines.h

        defines.h文件包含了游戏使用的大量的定义和枚举变量。defines.h头文件将包含游戏或引擎将用到的常用定义.

    #ifndef _UGP_DEFINES_H_
    #define _UGP_DEFINES_H_

    #include
    <windows.h>

    // Boolean values.
    #define UGP_INVALID -1
    #define UGP_OK 1
    #define UGP_FAIL 0

    // Window handle (need new way if porting to Mac and OpenGL).
    #define WinHWND HWND

    // Typedefs and enumerations.
    typedef long VertexType;

    enum PrimType
    {
    NULL_TYPE,
    POINT_LIST,
    TRIANGLE_LIST,
    TRIANGLE_STRIP,
    TRIANGLE_FAN,
    LINE_LIST,
    LINE_STRIP
    };

    // Color defines.
    #define UGPCOLOR_ARGB(a,r,g,b) ((unsigned long)((((a)&0xff)<<24)|\
    (((r)
    &0xff)<<16)|(((g)&0xff)<<8)|\
    ((b)
    &0xff)))

    #endif

      

    RenderInterface.h

    RenderInterface.h头文件包含了渲染系统基类的声明。然后派生该类以创建游戏引擎使用的真实渲染系统。

     渲染系统的基类所包含的成员变量有屏幕宽度和高度、一个是否渲染整个屏幕的标识符,Direct3D初始化函数所需要的窗口句柄,以及两个投影矩阵所需的近距离值和远距离值。将变量属性设为受保护的(protected),意味着它们可以是派生类的成员变量,就如同是在那些类中声明的一样。

       这些渲染系统的基类开始先是构造函数和析构函数。这些构造函数只是简单地设置成员变量的默认值,而析构函数什么也不做。析构函数的属性被设置为虚拟的(virtual),因为这样可以确保所有的派生类在析构时可以调用正确的析构函数。如果不这样的话,读者可能就会遇到一些意外错误或是很难发现的内存泄漏问题。在创建基类时,要牢记一定要创建一个虚拟析构函数。

    函数的其余部分直接明了。Initialize()函数用于设置Direct3D渲染系统。OneTimeInit()函数调用只需调用代码一次,这就像设置投影矩阵一样。一旦应用程序使用Shutdown()函数,它就会清除渲染系统。在Direct3D中可以释放那些在系统运行过程中用到的Direct3D对象。SetClearCol()函数用于将后台缓存颜色设置为指定的颜色。StartRender()和EndRendering()这两个函数用于启动新场景,结束场景,在渲染场景之前、之后或过程中清除场景。CalculateProjMatrix()和CalculateOrthoMatrix()这两个函数用于设置可以使用立体投影和正交投影的两个矩阵。CreateStaticBuffer()函数用于创建要绘制的静态顶点缓存,Render()函数用于将缓存内容显示在屏幕上。由于OpenGL中没有像Direct3D一样的顶点缓存,因此如果要移植到OpenGL中,就可以设置这些内容,只要用static buffer(静态缓存)类指定浮点数组即可。OpenGL版的Render()函数可以使用顶点数组或OpenGL顶点缓存对象(VBOs)渲染静态缓存内容。唯一的差异在于OpenGL并没有像Direct3D这样创建顶点缓存的结构,但这对于代码移植而言并不是问题。

    #ifndef _UGP_RENDERINTERFACE_H_
    #define _UGP_RENDERINTERFACE_H_

    #include
    "defines.h"


    class CRenderInterface
    {
    public:
    CRenderInterface() : m_screenWidth(
    0),
    m_screenHeight(
    0), m_near(0), m_far(0) { }
    virtual ~CRenderInterface() {}

    virtual bool Initialize(int w, int h,
    WinHWND mainWin,
    bool fullScreen) = 0;
    virtual void OneTimeInit() = 0;
    virtual void Shutdown() = 0;

    virtual void SetClearCol(float r, float g, float b) = 0;
    virtual void StartRender(bool bColor, bool bDepth,
    bool bStencil) = 0;
    virtual void ClearBuffers(bool bColor, bool bDepth,
    bool bStencil) = 0;
    virtual void EndRendering() = 0;

    virtual void CalculateProjMatrix(float fov, float n,
    float f) = 0;
    virtual void CalculateOrthoMatrix(float n, float f) = 0;

    virtual int CreateStaticBuffer(VertexType, PrimType,
    int totalVerts, int totalIndices,
    int stride, void **data, unsigned int *indices,
    int *staticId) = 0;

    virtual int Render(int staticId) = 0;

    protected:
    int m_screenWidth;
    int m_screenHeight;
    bool m_fullscreen;

    WinHWND m_mainHandle;

    float m_near;
    float m_far;
    };

    #endif

    engine.h

          engine.h文件包含了include语句,这样就可以在一个地方访问游戏引擎的不同内容。这里只包含了渲染系统。诚如所知道的一样,该文件的内容将随着游戏的开发进度而发生变动。

    #ifndef _UGP_ENGINE_H_
    #define _UGP_ENGINE_H_

    #include
    "RenderInterface.h"
    #include
    "D3DRenderer.h"

    #endif

      

    D3DRenderer.h

    D3DRenderer.h头文件定义了本书一直要用到的派生渲染类。除了该类将用于实现具体的渲染功能之外,它的定义与基类没有任何区别。类还声明了几个具体的Direct3D成员变量。

     首先,D3DRenderer.h头文件包含和绑定了具体的Direct3D头和库。接下来是Direct3D静态缓存的声明。该缓存用顶点缓存将静态几何图形(非动画的)绘制到屏幕上。静态缓存结构由顶点缓存、索引缓存(三角形索引)、对顶点和索引的计算、单个顶点尺寸的幅度值、Direct3D顶点FVF以及在渲染静态缓存时要用的图元类型。

           D3D渲染系统为Direct3d9对象详细说明了成员变量、Direct3D设备对象、清除色、一个用于确认它是否位于当前正在渲染的场景中的标识符、保存所有静态缓存的数组链表、静态缓存数目的计数器以及正在使用的当前静态缓存变量。最后一个变量是为了避免设置已经设置过的静态缓存。当有必要在单独一帧中多次渲染相同的对象时,会多次出现这种情况。每次设置相同的静态缓存都要浪费处理时间,都会影响到程序性能。在和纹理图像打交道,尤其是和大纹理图像和对象的多个实例打交道时,更是值得注意。

           文件结尾处声明的最后一个函数原型是CreateD3DRenderer()。实际上并不需要该函数,但是有了该函数,调用它就可以为渲染系统分配内存。当使用动态链接库(DLL),也就是一个用于Direct3D,一个用于OpenGL时,它们会非常有用。如果在这两个动态链接库中都有CreateRenderer()函数,它就会起作用。这样在程序运行期间,就可以为渲染系统分配要用的动态链接库。就可以让程序和渲染系统使用的对象无关。程序并不知道使用的是哪个渲染系统,它只要知道无论它用哪个渲染系统,都要指定它所用的动态链接库。

    #ifndef _D3D_RENDERER_H_
    #define _D3D_RENDERER_H_

    #include
    <windows.h>
    #include
    <d3d9.h>
    #include
    <d3dx9.h>
    #include
    "RenderInterface.h"

    #pragma comment(lib, "d3d9.lib")
    #pragma comment(lib, "d3dx9.lib")


    struct stD3DStaticBuffer
    {
    stD3DStaticBuffer() : vbPtr(
    0), ibPtr(0), numVerts(0),
    numIndices(
    0), stride(0), fvf(0),
    primType(NULL_TYPE) {}

    LPDIRECT3DVERTEXBUFFER9 vbPtr;
    LPDIRECT3DINDEXBUFFER9 ibPtr;
    int numVerts;
    int numIndices;
    int stride;
    unsigned
    long fvf;
    PrimType primType;
    };


    class CD3DRenderer : public CRenderInterface
    {
    public:
    CD3DRenderer();
    ~CD3DRenderer();

    bool Initialize(int w, int h, WinHWND mainWin,
    bool fullScreen);
    void Shutdown();

    void SetClearCol(float r, float g, float b);
    void StartRender(bool bColor, bool bDepth, bool bStencil);
    void ClearBuffers(bool bColor, bool bDepth, bool bStencil);
    void EndRendering();

    void CalculateProjMatrix(float fov, float n, float f);
    void CalculateOrthoMatrix(float n, float f);

    int CreateStaticBuffer(VertexType, PrimType,
    int totalVerts, int totalIndices,
    int stride, void **data, unsigned int *indices,
    int *staticId);

    int Render(int staticId);

    private:
    void OneTimeInit();


    private:
    D3DCOLOR m_Color;
    LPDIRECT3D9 m_Direct3D;
    LPDIRECT3DDEVICE9 m_Device;
    bool m_renderingScene;

    stD3DStaticBuffer
    *m_staticBufferList;
    int m_numStaticBuffers;
    int m_activeStaticBuffer;
    };

    bool CreateD3DRenderer(CRenderInterface **pObj);

    #endif

      

    D3DRenderer.cpp

     D3DRenderer.cpp源文件开始先声明了CreateD3DRenderer()函数和CD3DRenderer类的构造函数和析构函数。CreateD3DRenderer()函数简单地实现了内存分配,以创建一个新的渲染对象。然后新对象存储在发送给函数的基类指针中。这样游戏只要和基类对象打交道就可以了,而不需要知道该对象是OpenGL还是Direct3D生成的对象。构造函数初始化类成员变量,而析构函数调用Shutdown()函数以确保在销毁对象前系统被清理干净。程序清单2.8显示了前三个函数。

    #include"D3DRenderer.h"


    bool CreateD3DRenderer(CRenderInterface **pObj)
    {
    if(!*pObj) *pObj = new CD3DRenderer;
    else return false;

    return true;
    }

    unsigned
    long CreateD3DFVF(int flags)
    {
    unsigned
    long fvf = 0;

    return fvf;
    }


    CD3DRenderer::CD3DRenderer()
    {
    m_Direct3D
    = NULL;
    m_Device
    = NULL;
    m_renderingScene
    = false;
    m_numStaticBuffers
    = 0;
    m_activeStaticBuffer
    = UGP_INVALID;
    m_staticBufferList
    = NULL;
    }


    CD3DRenderer::
    ~CD3DRenderer()
    {
    Shutdown();
    }


    bool CD3DRenderer::Initialize(int w, int h, WinHWND mainWin,
    bool fullScreen)
    {
    Shutdown();

    m_mainHandle
    = mainWin;
    if(!m_mainHandle) return false;

    m_fullscreen
    = fullScreen;

    D3DDISPLAYMODE mode;
    D3DCAPS9 caps;
    D3DPRESENT_PARAMETERS Params;

    ZeroMemory(
    &Params, sizeof(Params));

    m_Direct3D
    = Direct3DCreate9(D3D_SDK_VERSION);
    if(!m_Direct3D) return false;

    if(FAILED(m_Direct3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,
    &mode))) return false;

    if(FAILED(m_Direct3D->GetDeviceCaps(D3DADAPTER_DEFAULT,
    D3DDEVTYPE_HAL,
    &caps))) return false;

    DWORD processing
    = 0;
    if(caps.VertexProcessingCaps != 0)
    processing
    = D3DCREATE_HARDWARE_VERTEXPROCESSING |
    D3DCREATE_PUREDEVICE;
    else
    processing
    = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

    if(m_fullscreen)
    {
    Params.FullScreen_RefreshRateInHz
    = mode.RefreshRate;
    Params.PresentationInterval
    = D3DPRESENT_INTERVAL_ONE;
    }
    else
    Params.PresentationInterval
    = D3DPRESENT_INTERVAL_IMMEDIATE;

    Params.Windowed
    = !m_fullscreen;
    Params.BackBufferWidth
    = w;
    Params.BackBufferHeight
    = h;
    Params.hDeviceWindow
    = m_mainHandle;
    Params.SwapEffect
    = D3DSWAPEFFECT_DISCARD;
    Params.BackBufferFormat
    = mode.Format;
    Params.BackBufferCount
    = 1;
    Params.EnableAutoDepthStencil
    = TRUE;
    Params.AutoDepthStencilFormat
    = D3DFMT_D16;

    m_screenWidth
    = w;
    m_screenHeight
    = h;

    if(FAILED(m_Direct3D->CreateDevice(D3DADAPTER_DEFAULT,
    D3DDEVTYPE_HAL, m_mainHandle, processing,
    &Params, &m_Device))) return false;

    if(m_Device == NULL) return false;

    OneTimeInit();
    return true;
    }


    void CD3DRenderer::OneTimeInit()
    {
    if(!m_Device) return;

    m_Device
    ->SetRenderState(D3DRS_LIGHTING, FALSE);
    m_Device
    ->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);

    CalculateProjMatrix(D3DX_PI
    / 4, 0.1f, 1000);
    }


    void CD3DRenderer::Shutdown()
    {
    for(int s = 0; s < m_numStaticBuffers; s++)
    {
    if(m_staticBufferList[s].vbPtr)
    {
    m_staticBufferList[s].vbPtr
    ->Release();
    m_staticBufferList[s].vbPtr
    = NULL;
    }

    if(m_staticBufferList[s].ibPtr)
    {
    m_staticBufferList[s].ibPtr
    ->Release();
    m_staticBufferList[s].ibPtr
    = NULL;
    }
    }

    m_numStaticBuffers
    = 0;
    if(m_staticBufferList) delete[] m_staticBufferList;
    m_staticBufferList
    = NULL;

    if(m_Device) m_Device->Release();
    if(m_Direct3D) m_Direct3D->Release();

    m_Device
    = NULL;
    m_Direct3D
    = NULL;
    }


    void CD3DRenderer::SetClearCol(float r, float g, float b)
    {
    m_Color
    = D3DCOLOR_COLORVALUE(r, g, b, 1.0f);
    }


    void CD3DRenderer::StartRender(bool bColor, bool bDepth,
    bool bStencil)
    {
    if(!m_Device) return;

    unsigned
    int buffers = 0;
    if(bColor) buffers |= D3DCLEAR_TARGET;
    if(bDepth) buffers |= D3DCLEAR_ZBUFFER;
    if(bStencil) buffers |= D3DCLEAR_STENCIL;

    if(FAILED(m_Device->Clear(0, NULL, buffers, m_Color, 1, 0)))
    return;
    if(FAILED(m_Device->BeginScene())) return;

    m_renderingScene
    = true;
    }


    void CD3DRenderer::ClearBuffers(bool bColor, bool bDepth,
    bool bStencil)
    {
    if(!m_Device) return;

    unsigned
    int buffers = 0;
    if(bColor) buffers |= D3DCLEAR_TARGET;
    if(bDepth) buffers |= D3DCLEAR_ZBUFFER;
    if(bStencil) buffers |= D3DCLEAR_STENCIL;

    if(m_renderingScene) m_Device->EndScene();
    if(FAILED(m_Device->Clear(0, NULL, buffers, m_Color, 1, 0)))
    return;

    if(m_renderingScene)
    if(FAILED(m_Device->BeginScene())) return;
    }


    void CD3DRenderer::EndRendering()
    {
    if(!m_Device) return;

    m_Device
    ->EndScene();
    m_Device
    ->Present(NULL, NULL, NULL, NULL);

    m_renderingScene
    = false;
    }


    void CD3DRenderer::CalculateProjMatrix(float fov, float n, float f)
    {
    if(!m_Device) return;
    D3DXMATRIX projection;

    D3DXMatrixPerspectiveFovLH(
    &projection, fov,
    (
    float)m_screenWidth/(float)m_screenHeight, n, f);

    m_Device
    ->SetTransform(D3DTS_PROJECTION, &projection);
    }


    void CD3DRenderer::CalculateOrthoMatrix(float n, float f)
    {
    if(!m_Device) return;
    D3DXMATRIX ortho;

    D3DXMatrixOrthoLH(
    &ortho, (float)m_screenWidth,
    (
    float)m_screenHeight, n, f);
    m_Device
    ->SetTransform(D3DTS_PROJECTION, &ortho);
    }


    int CD3DRenderer::CreateStaticBuffer(VertexType vType,
    PrimType primType,
    int totalVerts,
    int totalIndices, int stride, void **data,
    unsigned
    int *indices, int *staticId)
    {
    void *ptr;
    int index = m_numStaticBuffers;

    if(!m_staticBufferList)
    {
    m_staticBufferList
    = new stD3DStaticBuffer[1];
    if(!m_staticBufferList) return UGP_FAIL;
    }
    else
    {
    stD3DStaticBuffer
    *temp;
    temp
    = new stD3DStaticBuffer[m_numStaticBuffers + 1];

    memcpy(temp, m_staticBufferList,
    sizeof(stD3DStaticBuffer) * m_numStaticBuffers);

    delete[] m_staticBufferList;
    m_staticBufferList
    = temp;
    }

    m_staticBufferList[index].numVerts
    = totalVerts;
    m_staticBufferList[index].numIndices
    = totalIndices;
    m_staticBufferList[index].primType
    = primType;
    m_staticBufferList[index].stride
    = stride;
    m_staticBufferList[index].fvf
    = CreateD3DFVF(vType);

    if(totalIndices > 0)
    {
    if(FAILED(m_Device->CreateIndexBuffer(sizeof(unsigned int) *
    totalIndices, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16,
    D3DPOOL_DEFAULT,
    &m_staticBufferList[index].ibPtr,
    NULL)))
    return UGP_FAIL;

    if(FAILED(m_staticBufferList[index].ibPtr->Lock(0, 0,
    (
    void**)&ptr, 0))) return UGP_FAIL;

    memcpy(ptr, indices,
    sizeof(unsigned int) * totalIndices);
    m_staticBufferList[index].ibPtr
    ->Unlock();
    }
    else
    {
    m_staticBufferList[index].ibPtr
    = NULL;
    }

    if(FAILED(m_Device->CreateVertexBuffer(totalVerts * stride,
    D3DUSAGE_WRITEONLY, m_staticBufferList[index].fvf,
    D3DPOOL_DEFAULT,
    &m_staticBufferList[index].vbPtr,
    NULL)))
    return UGP_FAIL;

    if(FAILED(m_staticBufferList[index].vbPtr->Lock(0, 0,
    (
    void**)&ptr, 0))) return UGP_FAIL;

    memcpy(ptr, data, totalVerts
    * stride);
    m_staticBufferList[index].vbPtr
    ->Unlock();


    *staticId = m_numStaticBuffers;
    m_numStaticBuffers
    ++;

    return UGP_OK;
    }


    int CD3DRenderer::Render(int staticId)
    {
    if(staticId >= m_numStaticBuffers) return UGP_FAIL;

    if(m_activeStaticBuffer != staticId)
    {
    if(m_staticBufferList[staticId].ibPtr != NULL)
    m_Device
    ->SetIndices(m_staticBufferList[staticId].ibPtr);

    m_Device
    ->SetStreamSource(0,
    m_staticBufferList[staticId].vbPtr,
    0,
    m_staticBufferList[staticId].stride);

    m_Device
    ->SetFVF(m_staticBufferList[staticId].fvf);

    m_activeStaticBuffer
    = staticId;
    }

    if(m_staticBufferList[staticId].ibPtr != NULL)
    {
    switch(m_staticBufferList[staticId].primType)
    {
    case POINT_LIST:
    if(FAILED(m_Device->DrawPrimitive(D3DPT_POINTLIST,
    0, m_staticBufferList[staticId].numVerts)))
    return UGP_FAIL;
    break;

    case TRIANGLE_LIST:
    if(FAILED(m_Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0,
    0, m_staticBufferList[staticId].numVerts / 3,
    0, m_staticBufferList[staticId].numIndices)))
    return UGP_FAIL;
    break;

    case TRIANGLE_STRIP:
    if(FAILED(m_Device->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0,
    0, m_staticBufferList[staticId].numVerts / 2,
    0, m_staticBufferList[staticId].numIndices)))
    return UGP_FAIL;
    break;

    case TRIANGLE_FAN:
    if(FAILED(m_Device->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN, 0,
    0, m_staticBufferList[staticId].numVerts / 2,
    0, m_staticBufferList[staticId].numIndices)))
    return UGP_FAIL;
    break;

    case LINE_LIST:
    if(FAILED(m_Device->DrawIndexedPrimitive(D3DPT_LINELIST, 0,
    0, m_staticBufferList[staticId].numVerts / 2,
    0, m_staticBufferList[staticId].numIndices)))
    return UGP_FAIL;
    break;

    case LINE_STRIP:
    if(FAILED(m_Device->DrawIndexedPrimitive(D3DPT_LINESTRIP, 0,
    0, m_staticBufferList[staticId].numVerts,
    0, m_staticBufferList[staticId].numIndices)))
    return UGP_FAIL;
    break;

    default:
    return UGP_FAIL;
    }
    }
    else
    {
    switch(m_staticBufferList[staticId].primType)
    {
    case POINT_LIST:
    if(FAILED(m_Device->DrawPrimitive(D3DPT_POINTLIST,
    0, m_staticBufferList[staticId].numVerts)))
    return UGP_FAIL;
    break;

    case TRIANGLE_LIST:
    if(FAILED(m_Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0,
    (
    int)(m_staticBufferList[staticId].numVerts / 3))))
    return UGP_FAIL;
    break;

    case TRIANGLE_STRIP:
    if(FAILED(m_Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0,
    (
    int)(m_staticBufferList[staticId].numVerts / 2))))
    return UGP_FAIL;
    break;

    case TRIANGLE_FAN:
    if(FAILED(m_Device->DrawPrimitive(D3DPT_TRIANGLEFAN, 0,
    (
    int)(m_staticBufferList[staticId].numVerts / 2))))
    return UGP_FAIL;
    break;

    case LINE_LIST:
    if(FAILED(m_Device->DrawPrimitive(D3DPT_LINELIST, 0,
    m_staticBufferList[staticId].numVerts
    / 2)))
    return UGP_FAIL;
    break;

    case LINE_STRIP:
    if(FAILED(m_Device->DrawPrimitive(D3DPT_LINESTRIP, 0,
    m_staticBufferList[staticId].numVerts)))
    return UGP_FAIL;
    break;

    default:
    return UGP_FAIL;
    }
    }

    return UGP_OK;
    }

      Initialize()和OneTimeInit()两个函数。这两个函数就像本书第1章中的演示程序一样用于初始化Direct3D。Initialize()函数像前面一样以相同的方式设置Direct3D,所以该函数没有什么新的东西。该函数的最后部分调用OneTimeInit()函数,以完成附加的初始化工作。Initialize()函数以窗口宽度(w)、高度(h)和窗口句柄(mainWin)以及一个指向窗口是否以全屏形式显示的标识(fullScreen)为参数。OneTimeInit()函数在此设置默认的投影矩阵。

    Shutdown()函数主要负责清理所有渲染系统用过的内存。该函数在此循环检查,并释放所有的静态缓存数据,清理静态缓存列表,释放特定的Direct3D对象。

    接下来是SetClearCol()、StartRender()、ClearBuffers()和EndRendering()函数。SetClearCol()函数以清屏的红绿蓝三色的浮点值作为参数。StartRender()和ClearBuffers()函数使用三个布尔值指明系统是否清除颜色、深度和stencil缓存。最后一个参数对渲染没有任何作用。StartRender()函数用于启动一个新的场景,而ClearBuffers()用于清理已经启动的场景。EndRendering()函数没有任何参数,用于停止场景的渲染。

    下来是CalculateProjMatrix()和CalculateOrthoMatrix()函数。CalculateProjMatrix()函数用于创建平行投影矩阵,它有三个参数:视场(fv)、近距离(n)和远距离值(f)。CalculateOrthoMatrix()函数和CalculateProjMatrix()函数的功能相同,不过它创建的是一个正交投影矩阵,而且他只有两个参数:近距离值(n)和远距离值(f)。

      渲染系统中的倒数第二个函数是CreateStaticBuffer()。该函数的功能是设置静态缓存对象中的一个对象内容,并将其添加到静态缓存列表中。该函数的参数包括:正在使用的顶点类型(本书将在稍后的游戏开发项目中复习该参数)、渲染该几何图形(例如:三角形列表、顶点)的指令、几何图形中的顶点总数和指向新创建的将要保存的静态缓存ID的变量指针。最后一个参数用于保存静态缓存ID,这样就在绘制几何图形时可以将该值传递给Render()函数。 CreateStaticBuffer()函数设置一个静态缓存对象内容,并将其添加到静态缓存列表中。在将该静态缓存添加到列表后,就会创建索引和顶点缓存,并保存静态缓存ID,增加静态缓存总数。使用矩阵列表可以简化对象列表的创建。

    // 设置静态缓存对象中的一个对象内容,并将其添加到静态缓存列表中

    int CD3DRenderer::CreateStaticBuffer(

       VertexType vType,   // 正在使用的顶点类型

       PrimType primType,  // 渲染该几何图形(例如:三角形列表、顶点)的指令

       int totalVerts,     // 几何图形中的顶点总数

       int totalIndices,   // 几何图形中的索引总数

       int stride,         // 单个顶点尺寸的幅度值

       void **data,     // 保存顶点的数组

       unsigned int *indices, //保存索引的数组

       int *staticId       // 保存静态缓存ID的指针

       );

    这里,渲染系统中的最后一个函数是Render()。这个篇幅很长的函数包含了一个参数:静态缓存ID,它会将与该ID相关的几何图形渲染到屏幕上。函数最前面的部分快速检查静态缓存ID以确保其有效。接下来,该函数检查静态缓存ID是否可用。如果可用,它就会调用DrawPrimitive()函数渲染图形。如果静态缓存不可用,它就会调用SetStreamSource()和SetFvF()两个函数。可以像绘制无索引几何图形一样,Render()函数也可以绘制索引几何图形(使用索引的几何图形)。

  • 相关阅读:
    hadoop 2.x 简单实现wordCount
    httpClient连接超时设置
    Java io使用简介
    log4j使用教程
    F#中的自定义隐式转换
    Computation expressions and wrapper types
    Introducing 'bind'
    Understanding continuations
    Computation expressions: Introduction
    MySQL优化总结,百万级数据库优化方案
  • 原文地址:https://www.cnblogs.com/kex1n/p/2147371.html
Copyright © 2011-2022 走看看