首先,這個架構有3個檔案組成,d3dUtility.h/cpp與d3dinit.cpp。編寫的時候應該首先從d3dUtility.h開始。
在這個標頭檔中,包含了5個函數:initD3D, EnterMsgLoop, WndProc, Release和Delete。其中後兩個是兩個模板函數,主要用於Release和Delete對象,這兩個函數比較簡單,這裡就不說明了。
接下來,就需要在d3dUtility.cpp中實現這幾個函數。由於WndProc牽扯到對遊戲的控制(WM_KEYDOWN訊息的處理在WndProc這個回呼函數中),所以作者選擇將這個函數放到d3dinit.cpp中進行編寫。先看EnterMsgLoop這個函數:
int d3d::EnterMsgLoop(bool (*ptr_display)(float timeDelta))<br />{<br />MSG msg;<br />::ZeroMemory(&msg, sizeof(MSG));<br />static float lastTime = (float)timeGetTime();<br />while (msg.message != WM_QUIT)<br />{<br />if (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))<br />{<br />::TranslateMessage(&msg);<br />::DispatchMessage(&msg);<br />}<br />else<br />{<br />float currTime = (float)timeGetTime();<br />float timeDelta = (currTime - lastTime) * 0.001f;<br />ptr_display(timeDelta);<br />lastTime = currTime;<br />}<br />}<br />return msg.wParam;<br />}
這個函數中,主要就是對MSG的對象msg的判斷,根據其訊息類型判斷,如果沒有訊息,那麼就調用繪圖函數進行繪製,這個對於有過Windows遊戲編程經驗的人來說,應該不會陌生。
接下來是最關鍵的D3D初始化部分代碼,d3dInit()這個函數。這個函數可以看成兩大部分,第一部分是對Windows視窗的初始化,分為4步:
1.填充WNDCLASS結構體,並調用RegisterClass註冊這個結構體。
2.利用CreateWindow這個函數建立HWND對象。
3.調用ShowWindow方法顯示表單。
4.調用UpdateWindow方法更新表單。
需要注意的是,由於作者把d3dUtility放到了d3d這個命名空間中,因此這裡我們需要使用::來應用以上的這些函數。
然後就該初始化D3D了。初始化D3D的目的是為了建立IDirect3DDevice對象,這個對象用於之後的繪製映像等功能。為了初始化D3D,也有四步:
1.建立IDirect3D9對象,這個對象主要用於擷取裝置的能力以及建立IDirect3DDevice對象。
2.利用D3DCAPS9對象擷取顯示卡的能力,並判斷使用硬體頂點處理還是軟體頂點處理。使用一個int數vp記錄結果。其實這個vp還可以記錄其他的裝置資訊,但是作為一本教程的執行個體代碼,作者沒有判斷其他的Behavior。
3.填充D3DPRESENT_PARAMETERS結構。這個主要是設定顯示的效果。
4.利用d3d9->CreateDevice建立device。
至此初始化工作就完成了。咱們的d3dUtility也實現的差不多了,只有一個WndProc函數沒有實現,放到了d3dinit.cpp中來實現。
最後我們來看一下d3dinit.cpp這個檔案。大體瀏覽一下代碼,發現了WinMain這個函數。這個函數內部的執行思路非常清晰,首先初始化D3D,然後Setup,之後EnterMsgLoop,當使用者選擇退出之後(從EnterMsgLoop這個函數返回),則執行Cleanup方法,最後是釋放IDirect3DDevice9對象,並返回。