本系列以 MFC 為基礎框架,逐步建構 DirectX 8 應用程式,涵蓋框架搭建、Direct3D 初始化、三角形繪製、索引緩衝區、貼圖映射、3D 矩陣變換與 Z-Buffer 啟用,最終呈現旋轉貼圖立方體。適合已具備 MFC 基礎、欲入門 DirectX 8 的開發者。
CDX8MFCApp:應用程式類別,覆寫 InitInstance、ExitInstance、OnIdle。CFrameWin:主視窗類別,提供 Init、Go、Active、End、Update 等虛擬函數供衍生類擴充。// InitInstance: 建立主視窗並初始化
BOOL CDX8MFCApp::InitInstance()
{
m_pMainWnd = new CFrameWin();
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
Game = (CFrameWin*)m_pMainWnd;
Game->Init();
return TRUE;
}
// OnIdle: 遊戲主迴圈 (無訊息時持續被呼叫)
BOOL CDX8MFCApp::OnIdle(LONG lCount)
{
if (Game->window_active == TRUE) { Game->Active(); Game->window_active = FALSE; }
Game->Go();
return TRUE; // 返回 TRUE 讓 OnIdle 持續被呼叫
}
IDirect3D8 介面:pID3D = Direct3DCreate8(D3D_SDK_VERSION);pID3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);D3DPRESENT_PARAMETERS):視窗模式、交換效果、背景緩衝格式。IDirect3DDevice8:CreateDevice 指定硬體頂點處理 (D3DCREATE_SOFTWARE_VERTEXPROCESSING) 以相容性優先。pID3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);HRESULT CFrameWin::DrawScene()
{
HRESULT hr;
do {
hr = pID3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0,63,0,0), 0, 0); if(FAILED(hr)) break;
hr = pID3DDevice->BeginScene(); if(FAILED(hr)) break;
// 繪圖指令置於此處
hr = pID3DDevice->EndScene(); if(FAILED(hr)) break;
hr = pID3DDevice->Present(NULL, NULL, NULL, NULL);
} while(0);
return hr;
}
void CFrameWin::ShutdownDirect3D()
{
HELPER_RELEASE(pTexture);
HELPER_RELEASE(pIndexBuffer);
HELPER_RELEASE(pStreamData);
HELPER_RELEASE(pID3DDevice);
HELPER_RELEASE(pID3D);
}
struct MYVERTEX { FLOAT x, y, z; FLOAT rhw; DWORD color; };
#define D3DFVF_MYVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
pID3DDevice->CreateVertexBuffer(sizeof(MYVERTEX)*num_elems, D3DUSAGE_WRITEONLY,
D3DFVF_MYVERTEX, D3DPOOL_DEFAULT, &pStreamData);
MYVERTEX* v; pStreamData->Lock(0,0,(BYTE**)&v,0);
for(int i=0;iUnlock();
pID3DDevice->SetVertexShader(D3DFVF_MYVERTEX);
pID3DDevice->SetStreamSource(0, pStreamData, sizeof(MYVERTEX));
pID3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, num_elems/3);
使用 DrawIndexedPrimitive 減少重複頂點資料。建立索引緩衝區 (CreateIndexBuffer)、填充索引陣列、設定 SetIndices,最後呼叫 DrawIndexedPrimitive 繪製。
MYVERTEX 加入 tu, tv 材質座標。D3DXCreateTextureFromFile 載入位圖並 SetTexture(0, pTexture)。D3DFVF_TEX1。present.EnableAutoDepthStencil = TRUE;
present.AutoDepthStencilFormat = D3DFMT_D16;
pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
// DrawScene 中 Clear 加入 D3DCLEAR_ZBUFFER
void CFrameWin::BuildMatrices()
{
D3DXMATRIX mat;
// 世界矩陣:Y 軸旋轉
D3DXMatrixRotationY(&mat, timeGetTime()/1000.0f);
pID3DDevice->SetTransform(D3DTS_WORLD, &mat);
// 視圖矩陣:相機位置 (0,3,-5) 看向原點,上方向 Y 軸
D3DXMatrixLookAtLH(&mat, &D3DXVECTOR3(0,3,-5), &D3DXVECTOR3(0,0,0), &D3DXVECTOR3(0,1,0));
pID3DDevice->SetTransform(D3DTS_VIEW, &mat);
// 投影矩陣:45 度視野、4:3 比例、近平面 1、遠平面 100
D3DXMatrixPerspectiveFovLH(&mat, D3DX_PI/4, 4.0f/3.0f, 1.0f, 100.0f);
pID3DDevice->SetTransform(D3DTS_PROJECTION, &mat);
}
struct MYVERTEX { FLOAT x,y,z; DWORD color; FLOAT tu,tv; };
本系列完整展示了在 MFC 架構下整合 DirectX 8 的完整流程,從基本框架、裝置初始化、基本圖元繪製、索引優化、貼圖映射到 3D 矩陣變換與 Z-Buffer 啟用,最終實現旋轉貼圖立方體。原始碼可從 gamedev.363.net 下載或聯繫作者 laical@21cn.com 索取。