讓人很不爽的前兩天裝的directX9(decemeber)版和我看的這本《Direct3D游戲編程入門教程》有版本沖突。書里邊使用了 direct3D自己帶的框架,而這個框架和我裝的這個directX9是不一樣的,聽說這個版本包含了許多directX10的東西,可能是這個原因吧。
我反復想是用新的框架還是裝回較早的版本,看了directX自帶的tutorail和文檔是英文的,不利于我速成。要是用原來的版本呢,可能換回來還需要一些代價。想來想去最后還是把原來那個卸了,裝回原來的版本。先速成再說。
好,下面進入第5章的第一個例子-Basic。
這個是d3d通用框架中的應用程序基類,在WinMain()里邊聲明一個CD3DApplication對象,然后調用其Run()方法程序就跑起來了。簡單代碼如下:
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
CMyD3DApplication d3dApp;
InitCommonControls();
if( FAILED( d3dApp.Create( hInst ) ) )
return 0;
return d3dApp.Run();
}
我們再來看一下CMyD3DApplication的聲明:
class CMyD3DApplication : public CD3DApplication
{
LPDIRECT3DVERTEXBUFFER9 m_pVB; //vertice buffer的指針
DWORD m_dwSizeofVertices; //頂點數
protected:
HRESULT OneTimeSceneInit();
HRESULT InitDeviceObjects();
HRESULT RestoreDeviceObjects();
HRESULT InvalidateDeviceObjects();
HRESULT DeleteDeviceObjects();
HRESULT FinalCleanup();
HRESULT Render();
HRESULT FrameMove();
HRESULT ConfirmDevice( D3DCAPS9* pCaps, DWORD dwBehavior,
D3DFORMAT adapterFormat, D3DFORMAT backBufferFormat );
public:
CMyD3DApplication();
};
也很簡單,兩個成員變量的含義已經注釋出來。需要說明一下的就是該程序使用vertex buffer來處理頂點,也就是直接把頂點復制到顯卡可以直接訪問到的驅動程序緩沖中,這樣就不必每次復制頂點,提高了效率。下面介紹一下該類的方法的調用:
- 程序啟動的執行順序是:ConfirmDevice()->OneTimeSceneInit()->InitDeviceObject()->RestoreDeviceObjects().
- 程序運行期間會執行一個循環:FrameMove()->Render()
- 如果運行期間改變窗口大小,框架會調用:InvalidateDeviceObjects()->RestoreDeviceObjects();
- 如果通過F2或者菜單來更改設備(HAL或REF),調用:InvalidateDeviceObjects()-> DeleteDeviceObjects()->InitDeviceObjects()->RestoreDeviceObjects();
- 程序退出時執行:InvalidateDeviceObjects()->DeleteDeviceObjects()->FinalCleanUp().
下面說一下具體函數的含義:
- ConfirmDevice():最先被執行,用來檢查顯卡能力,如果顯卡不支持,框架會切換到使用參考光柵器,或切換為頂點軟件處理。具體參數見教材。
- OneTimeSceneInit():一次性永久初始化,初始化與設備無關的東西,與FinalCleanUp()搭配,初始化的數據可以在FinalCleanUp()中銷毀。
- InitDeviceObjects():初始化與設備相關的對象,如果通過F2使設備發生改變,那么就需要重新執行該初始化。與DeleteDeviceObjects()搭配。
- InvalidateDeviceObjects():對于窗口的大小改變做出響應。
- RestoreDeviceObjects():和InvalidateDeviceObjects()搭配,可以在窗口大小改變時重新設置投影矩陣和渲染狀態等等。除了在程序開始時以為,都會和InvalidateDeviceObjects()成對調用。
- DeleteDeviceObjects():在設備改變時對設備資源進行銷毀。
- Render():作為3D渲染的入口點在每一幀時被調用,可以設置render state,clear buffer,渲染場景。
- FrameMove():容納所有動畫的代碼。
- FinalCleanUp():銷毀幾何數據和文件對象等等非設備資源。
OK,了解了執行過程,下面看一下重要步驟。
在Basic例子程,程序較為簡單,繪制了一個無須任何坐標變換和投影的四邊形,并用 m_d3dEnumeration.AppUsesDepthBuffer = FALSE;設置了不使用深度緩存。這里邊重要的方法就是RestoreDeviceObjects()中創建頂點緩沖區:
m_pd3dDevice->CreateVertexBuffer( m_dwSizeofVertices, D3DUSAGE_WRITEONLY, FVF,D3DPOOL_MANAGED,&m_pVB, NULL )
這里m_dwSizeofVertices是頂點數,m_pVB是緩沖區指針,比較好理解。FVF表示每個頂點的表示形式,定義成const DWORD FVF = (D3DFVF_XYZRHW | D3DFVF_DIFFUSE);表示每個頂點由(x,y,z,rhw,diffuse)構成,direct3D的頂點表示還有specular, normal,紋理等信息,分別對應不同的變量組合。
D3DPOOL_MANAGED是指定了D3D的資源管理器,負責對于紋理和幾何數據實施統一管理。D3D的資源管理器分成五種:
- D3DPOOL_DEFAULT:資源存儲在AGP或顯存中,在頂點緩沖或索引緩沖經常更新的情況下使用,避免內存到顯存的拷貝“過慢”。對于永遠不變的紋理,用默認池就是一種好的選擇。
- D3DPOOL_MANAGED:托管池,資源存儲在AGP或者顯存中,并在系統內存中有一份拷貝。只有內存發生變化才需要拷貝到顯存,如果性能不是最重要的,托管池永遠是一種最安全的選擇。
- D3DPOOL_SYSTEMMEN:系統池,存儲在系統內存中,設備丟失后(在全屏和窗口模式切換時或者改變分辨率)資源不需要重建。
- D3DPOOL_SCRATCH:臨時池,資源存儲在系統內存中,且設備丟失時無法重建,連同CreateOffScreenPlainSurface()一起使用,用于創建圖像表面。
- D3DPOOL_FORCE_DWORD:
創建頂點緩沖器之后,是Lock()頂點緩沖器,然后執行memcpy()拷貝頂點,之后UnLock().這里Lock()包含四個參數, offsetToLock是鎖定頂點緩沖區從哪個偏移開始,SizeToLock是鎖定的大小,ppbData是返回指向內存緩沖區的指針,最后一個是指定如何使用頂點緩沖器.
最后看一下Render()方法:
HRESULT CMyD3DApplication::Render()
{
// Begin the scene
if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
{
// In DX8: m_pd3dDevice->SetVertexShader( D3DFVF_CUSTOMVERTEX );
// Passing an FVF to IDirect3DDevice9::SetFVF specifies a legacy FVF with stream 0.
m_pd3dDevice->SetFVF(FVF ); // new in DX9
// DX8: only three parameters. In DX9 the third parameter is new
m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(VERTEX) );
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
// End the scene.
m_pd3dDevice->EndScene();
}
return S_OK;
}
Render()方法中首先使用m_pd3dDevice初始化一個場景 BeginScene(),使場景處于處理過程中,這樣后邊的繪制才會奏效,否則都會返回D3DERR_SCENE_NOT_IN_SCENE的錯誤。結束繪制以后再調用EndScene()清除標識場景處于處理過程的標志,刷新緩存數據以及確認渲染表面完好。
SetFVF()只有一個參數,就是頂點的結構,該方法僅用于固定流水線,對于使用shader的情況要調用SetVertexShader().
SetStreamSource()設置了數據流,DrawPrimitive()把數據渲染出來。
over!
原文地址:http://blog.sina.com.cn/u/40d00f170100012z