天天看點

DirectX 遊戲程式設計之遊戲架構

按照之前兩篇文章将書寫DirectX的遊戲架構代碼

DirectX 遊戲程式設計之開篇

DirectX 遊戲程式設計之3D空間,頂點緩存及索引緩存

開發環境:vs2012, DirectX SDK (June 2010),C++

對外接口:

bool DirectCDemo(HINSTANCE hInstance, RenderFunc renderfunc);
           

其中RenderFunc為繪制函數,定義為

typedef void (*RenderFunc)();
           

繪制一個按頂點着色的四面體,代碼可以如下

int WINAPI WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpCmdLine,
	int nCmdShow)
{
	DirectCDemo(hInstance, RenderVertex);
	return 0;
}
           

通過檢視繪制函數中的頂點資料,索引資料的定義以及繪制流程可以一窺我們的封裝代碼,繪制過程簡單如下:

0 建立視窗,初始化Direct3D。

以下,提供完整的初始化Direct3D過程

bool GameWnd::InitDirect3D(HWND hwnd, bool fullscreen)
{
	// Step 1: Create D3DDirect3D
	D3DDirect3D = Direct3DCreate9(D3D_SDK_VERSION);
	D3DPRESENT_PARAMETERS d3dpp;

	// Step 2: Set D3DPRESENT_PARAMETERS
	ZeroMemory(&d3dpp, sizeof(d3dpp));
	if(isMulBackBuffer)
		d3dpp.BackBufferCount = 2;
	else d3dpp.BackBufferCount = 1;
	// Enable depth and stencil
	
	if(isZBuffer)
		d3dpp.EnableAutoDepthStencil = TRUE;
	else
		d3dpp.EnableAutoDepthStencil = FALSE;

	d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

	if (fullscreen)
	{
		d3dpp.BackBufferWidth = window_width;
		d3dpp.BackBufferHeight = window_height;
		if(COLOR_FORMAT_DEFAULT==32)
			d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
		else 
			d3dpp.BackBufferFormat = D3DFMT_R5G6B5;
		d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
		d3dpp.Windowed = FALSE;
		d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
	}
	else
	{
		d3dpp.Windowed = TRUE;
		// Always default display mode in 32 bits.
		d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
		d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	}

	D3DDEVTYPE devtype = D3DDEVTYPE_HAL;

	// Set depth and stencil format

	if(isStencilBuffer && isZBuffer)
	{
		d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;

		if (FAILED(D3DDirect3D->CheckDeviceFormat(D3DADAPTER_DEFAULT,devtype,
			d3dpp.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
			D3DRTYPE_SURFACE, d3dpp.AutoDepthStencilFormat)))
		{
			d3dpp.AutoDepthStencilFormat = D3DFMT_D24X4S4;

			if (FAILED(D3DDirect3D->CheckDeviceFormat(D3DADAPTER_DEFAULT,devtype,
				d3dpp.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
				D3DRTYPE_SURFACE, d3dpp.AutoDepthStencilFormat)))
			{
				// Device does not support stencilbuffer
			}
		}
	}
	// Do not use stencil buffer
	else if (!isStencilBuffer && isZBuffer)
	{
		d3dpp.AutoDepthStencilFormat = D3DFMT_D32;

		if (FAILED(D3DDirect3D->CheckDeviceFormat(D3DADAPTER_DEFAULT,devtype,
			d3dpp.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
			D3DRTYPE_SURFACE, d3dpp.AutoDepthStencilFormat)))
		{
			d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
			if (FAILED(D3DDirect3D->CheckDeviceFormat(D3DADAPTER_DEFAULT,devtype,
				d3dpp.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
				D3DRTYPE_SURFACE, d3dpp.AutoDepthStencilFormat)))
			{
				// Device does not support required depth buffer
				return false;
			}
		}
	}


	// Step 3: Create D3DDirect3D device
	HRESULT hr = D3DDirect3D->CreateDevice(D3DADAPTER_DEFAULT, devtype, hwnd,
		D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &D3DDevice);

	if (FAILED(hr))
		hr = D3DDirect3D->CreateDevice(D3DADAPTER_DEFAULT, devtype, hwnd,
		D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &D3DDevice);

	if (FAILED(hr))
		hr = D3DDirect3D->CreateDevice(D3DADAPTER_DEFAULT, devtype, hwnd,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &D3DDevice);

	if (!D3DDevice)
	{
		// Was not able to create DIRECT3D9 device.
		return false;
	}
	D3DDevice->GetDeviceCaps(&D3DCaps);

	return true;
}
           

幾點需要注意:

如果開啟了自動深度緩存,模闆緩存管理,必須設定深度緩存,模闆緩存的格式,否則建立Device失敗

d3dpp.EnableAutoDepthStencil
           
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;  // 同時設定深度緩存與模闆緩存位數
           
d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;  // 隻開啟深度緩存
           

1 定義頂點資料,我們已經知道可以使用靈活頂點格式(Flexible Vertex Format,FVF)來自定義頂點格式,我們的标準頂點格式被定義為

D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1
           

結構體為

struct Vertex
{
	Vertex() {}
	Vertex(float x, float y, float z,
		float nx, float ny, float nz,
		Color c,
		float u, float v) : position(x,y,z),normal(nx,ny,nz),color(c), texCoords(u,v)
	{
	}
	Position3D position;
	Position3D normal;
	Color color;
	Position2D texCoords;
};
           

2 按照頂點資料定義索引,其實這就是一個short的索引數組,索引資料的類型以可以在繪制時指定

3 設定錄影機的投影(PROJECT),視圖(VIEW)矩陣

4 渲染材質,這部分将對DirectX的許多參數進行設定,例如開關光照、繪制網格、深度測試、模闆測試等

5 繪制頂點,将設定頂點格式,提供一個更加簡單的頂點繪制函數DrawIndexedPrimitiveUP

HRESULT DrawIndexedPrimitiveUP(
  [in]       D3DPRIMITIVETYPE PrimitiveType,   // 基本圖元類型,基本為三角形清單D3DPT_TRIANGLELIST
  [in]       UINT             MinVertexIndex,  // 最小頂點索引,由于使用的是基于0的頂點索引,一般為0
  [in]       UINT             NumVertices,   // 頂點數目,并非為索引數目,Demo中為4(四面體)
  [in]       UINT             PrimitiveCount,  //圖元數目,三角形個數
  [in] const void             *pIndexData,  // 索引資料
  [in]       D3DFORMAT        IndexDataFormat,  // 索引資料類型short則為16
  [in] const void             *pVertexStreamZeroData,  // 頂點資料
  [in]       UINT             VertexStreamZeroStride  // 頂點結構大小sizeof(Vertex)
);
           
DirectX 遊戲程式設計之遊戲架構

代碼位址git:[email protected]:hrlnldy/directxdemo.git

繼續閱讀