工程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()函数也可以绘制索引几何图形(使用索引的几何图形)。

13. GameProjec1_GameEngine相关推荐

  1. mahout安装测试

    Mahout 是 Apache Software Foundation(ASF) 旗下的一个开源项目,提供一些可扩展的机器学习领域经典算法的实现,旨在帮助开发人员更加方便快捷地创建智能应用程序.Apa ...

  2. ImportError: DLL load failed: 找不到指定的模块。 TensorFlow 1.13

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/zhenlingcn/article/details/88647288 问题描述 问题环境 Tenso ...

  3. iPhone 14 与iPhone 13

    iPhone 14 与iPhone 13 iPhone14Pro配置曝光:感叹号+4800w像素 | 小米12Ultra 最新套壳图 距离下一代iPhone发布还有半年之久,关于iPhone14系列的 ...

  4. PyTorch 笔记(13)— autograd(0.4 之前和之后版本差异)、Tensor(张量)、Gradient(梯度)

    1. 背景简述 torch.autograd 是 PyTorch 中方便用户使用,专门开发的一套自动求导引擎,它能够根据输入和前向传播过程自动构建计算图,并执行反向传播. 计算图是现代深度学习框架 P ...

  5. 机器学习入门(13)— Affine 仿射层、Softmax 归一化指数函数层实现

    1. 一维 Affine 仿射层 我们回顾下之前为了计算加权信号的总和,使用了矩阵的乘积运算 NumPy 中是 np.dot() , 参照代码如下: In [7]: X = np.random.ran ...

  6. 读书笔记2013第13本:《怎样解题》

    <怎样解题>这本书是在看<编程大师访谈录>(中文版第12页)这本书时无意发现的,一个编程大师推荐这本书来指导编程设计,google到这本书后粗略地翻看了一遍,发现是一本教学生如 ...

  7. [14] 薪酬迅速翻倍的13条跳槽原则

    首先,真正的高级人才是不用找工作的,因为只有被工作找的份. 但是,难免有些高级人才厌倦了旧的工作环境,或者遇到天花板,没有了发展空间,或者遇到新老板上任后排除异己来提拔自己的亲信等等,如果您真打算自己 ...

  8. centos6.5 php5.2,Linux中PHP安装与配置(CentOS-6.5:php-5.2.13)

    1 PHP简介     PHP(PHP: Hypertext Preprocessor的缩写,中文名:"超文本预处理器")是一种通用开源脚本语言.语法吸收了C语言.Java和Per ...

  9. 乐高无限无法进入服务器,乐高无限6.13更新 无法进入游戏问题修复

    乐高无限于13日例常更新,那么这次更新了什么内容呢,修复了哪些东西呢,下面就跟随小编一起去了解一下详细内容吧. 生存模式: 1.解决了在玩法模式中使用假日烟花异常的问题; 2.解决了昵称中包含部分特殊 ...

  10. 福建省2013高职单招计算机类试题,13年福建-高职单招-计算机类试题及答案.doc

    计算机类专业基础知识试题 第Ⅰ卷 单项选择题(在每小题的四个备选答案中,选出一个正确答案,并将正确的字母标号填涂在答题卡相应在位置上,每小题3分,共120分) 世界上第一台计算机(ENIAC)诞生的时 ...

最新文章

  1. 因未发项目奖金,一名程序员决定删代码泄愤
  2. Redis 热点 Key 如何发现?又该如何解决?
  3. 【数学与算法】贝塞尔曲线
  4. android:process=.server,Android启动(三)----开启SystemServer进程
  5. mysql报错注入实战_MySQL手工注入实战
  6. 三星:Android之外,技术为王
  7. python必备基础代码-【Python基础系列】常见的数据预处理方法(附代码)
  8. 在mysql上发布jbpm4.3
  9. nginx php上传配置
  10. 中国单箱梁体最宽矮塔斜拉桥合龙
  11. 敏捷开发Sprint周期总结
  12. NXP TJA1043 datasheet 知识点记录
  13. 推荐一些北京的景点(1简单版)
  14. autojs切换输入法
  15. linux swap空间不足,swap空间不足问题解决
  16. 微信小程序:页面传递中文出现乱码
  17. 欢迎大家访问我的网站
  18. <Notes>城市复杂环境的视觉定位与建图(报告人:上交邹丹平教授)
  19. idea热部署插件JRebel激活(强烈推荐,试试就离不开了)
  20. MATLAB矩阵变换

热门文章

  1. Android AlertDialog创建过程详解
  2. window对象小结
  3. java导入hbase_如何用java导入hbase.dat文件
  4. c语言课程性质,c语言课程的特性
  5. 路由器刷breed web控制台助手_红米AC2100路由器从零认证登录SCUT校园网踩坑经历...
  6. mysql三台部署_使用三台主机部署LNMP
  7. mysql实现分布式锁_数据库实现分布式锁
  8. mysqloffset什么意思_mysql查询时offset过大影响性能的原因和优化详解
  9. python表格数据过滤复制到另外一个表格
  10. 帆软Tab控件与控制组件隐藏的异同点