您好,登錄后才能下訂單哦!
筆記一中我們介紹了如何用代碼創建空的win32窗口,然而創建空的win32窗口只完成了一半的工作,接下來要做的工作是設置Direct3D,從而可以在屏幕上渲染圖形。
Direct3D要調用很多函數才能成功設置API。一旦完成設置,并且設置成功,就可以向屏幕上渲染圖形。
下面是函數中設置Direct3D所需的最少代碼。
- bool InitializeD3D(HWND hWnd, bool fullscreen)
- {
- D3DDISPLAYMODE displayMode;
- // Create the D3D object.
- g_D3D = Direct3DCreate9(D3D_SDK_VERSION);
- if(g_D3D == NULL) return false;
- // Get the desktop display mode.
- if(FAILED(g_D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode)))
- return false;
- // Set up the structure used to create the D3DDevice
- D3DPRESENT_PARAMETERS d3dpp;
- ZeroMemory(&d3dpp, sizeof(d3dpp));
- if(fullscreen)
- {
- d3dpp.Windowed = FALSE;
- d3dpp.BackBufferWidth = 640;
- d3dpp.BackBufferHeight = 480;
- }
- else
- d3dpp.Windowed = TRUE;
- d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
- d3dpp.BackBufferFormat = displayMode.Format;
- // Create the D3DDevice
- if(FAILED(g_D3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
- D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_D3DDevice)))
- {
- return false;
- }
- return true;
- }
上段代碼中的InitializeD3D函數的參數有窗口句柄hWnd,標識窗口是否全屏的標識符fullscreen。窗口句柄是在調用CreateWindows()函數創建窗口句柄時,返回給WinMain()函數的數值。InitializeD3D()函數開始先調用Direct3DCreat9()函數。Direct3DCreat9()函數將創建一個Direct3D接口對象,并返回該對象。該函數所帶的參數值為D3D_SDK_VERSION。如果從該函數創建的接口不為NULL(空),那么接口創建成功。如果是NULL,那么創建接口時就會出錯。其他步驟很大程度上取決于是否成功調用Direct3DCreat9()函數,所以一旦出現錯誤,就會立刻退出Direct3D初始化程序。
接下來調用的是GetAdapterDisplayMode()
函數。該函數將返回當前的顯示信息,如桌面分辨率(寬度和高度),顯示格式,顯示器的刷新頻率等。該函數的參數包括正在查詢的適配器以及保存信息的顯示模式對象。將D3DADAPTER_DEFAULT發送給函數,詳細說明代碼,通過這些代碼可以獲取想要的主顯卡信息。
檢索顯卡信息之后,函數接下來會創建D3DPRESENT_PARAMETERS對象。D3DPRESENT_PARAMETERS結構用于定義Direct3D窗口的顯示信息。這樣可以設置正在創建窗口的期望寬度和高度,刷新率,顯示模式為全屏或窗口,后天緩存數目等。
D3DPRESENT_PARAMETERS結構體的定義:
- typedef struct _D3DPRESENT_PARAMETERS_ {
- UINT BackBufferWidth; //窗口寬度
- UINT BackBufferHeight; //窗口高度
- D3DFORMAT BackBufferFormat; //渲染后臺緩存的格式
- UINT BackBufferCount; //想要用于渲染的后臺緩存總數
- D3DMULTISAMPLE_TYPE MultiSampleType;
- D3DSWAPEFFECT SwapEffect;
- HWND hDeviceWindow;
- BOOL Windowed;
- BOOL EnableAutoDepthStencil;
- D3DFORMAT AutoDepthStencilFormat;
- DWORD Flags;
- UINT FullScreen_RefreshRateInHz;
- UINT FullScreen_PresentationInterval;
- } D3DPRESENT_PARAMETERS;
D3DPRESENT_PARAMETERS結構體是的前兩個變量是BackBufferWidth( 窗口寬度 ),BackBufferHeight(窗口高度)。接下來的變量BackBufferFormat代表渲染后臺緩存的格式。將D3DFMT_DEFAULT發送給該參數,就會得到所要用到的桌面格式。該參數可以接收的其他參數值分別是D3DFMT_A2R10G10B10(紅、綠、藍各10位,Alpha通道2位,總計32位),D3DFMT_A8R8G8B8(紅、綠、藍Alpha各8位,總計32位)、D3DFMT_X8R8G8B8、D3DFMT_AIR5G5B5、D3DFMT_XIR5G5B5和D3DFMT_R5G5B5。
BcakBufferCount是想要用于渲染的后臺緩存總數。通常,使用一個后臺緩存和一個主緩存,使用多個緩存會使動畫更流暢,因為后臺緩存上繪制內容,然后將結果復制到主緩存,主緩存將其顯示在屏幕上。如果所有的事情都在主緩存處理,那么游戲玩家在玩游戲時,會看到正在刷新的屏幕,從而會產生視覺假象,破壞游
戲的視覺效果。成員變量MultiSampleType、MultiSampleQuality和SwapEffect處理交換效果。hDeviceWindow是調用WinMain()中的CreateWindow()函數創建的窗口句柄。Windowed標識符用于指定創建的窗口是否是全屏窗口。
EnableAutoDepthStencil標識符用于設置是否用Direct3D管理緩存深度以及模板緩存。AutoDepthStencilFormat將深度和模板緩存設置為BackBufferFormat可以使用的相同值之一。
結構中的最后三個變量分別是Flags、FullScreen_RefreshRateInHz和PresentationInterval。Flags標識符可以是D3DPRESENTFLAG_DEVICECLIP、D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL和D3DPRESENTFLAG_LOCKABLE_ BUFFER或D3DPRESENTFLAG_VIDEO的任意組合。變量FullScreen_RefreshRateInHz存儲顯示器的刷新率。對窗口模式程序而言,該值必須為0,但對全屏模式而言,該值取決于顯示器。對此,可以調用GetDisplayAdapter()函數獲取顯示模式。最后一個變量PresentationInterval處理可以顯示的交換鏈的后臺緩存的最大次數。交換鏈主要讓程序有多個窗口在桌面上同時顯示(每個渲染自己的窗口)本書不涉及交換鏈的討論,所以這里將不使用該變量。程序清單1.3 InitializeD3D()函數中調用的最后一個函數是CreateDevice()。該函數主要負責創建Direct3D設備對象,該對象用于向屏幕渲染圖形。如果函數失敗,最后一個參數(對象被發送給ppReturnedDeviceInterface)將為NULL(空)。測試函數是否失敗的另一種方法是判斷函數的返回值是否是D3D_OK以外的其他值。如果不是D3D_OK,則意味著創建過程中出現了問題,而且不會按照給定的規格創建設備。下面的代碼給出了CreateDevice()的函數原型。
CreateDevice()函數原型代碼如下:
- HRESULT CreateDevice( UINT Adapter,
- D3DDEVTYPE DeviceType,
- HWND hFocusWindow,
- DWORD BehaviorFlags,
- D3DPRESENT_PARAMETERS *pPresentationParameters,
- IDirect3DDevice9 **ppReturnedDeviceInterface
- );
CreateDevice()函數中的第一個參數是Adapter。該參數用于指定正在使用的顯卡。第二個參數DeviceType是一個標識符,用于指定Direct3D中的渲染方式。該參數的參數值可以是采用硬件渲染的D3DDEVTYPE_HAL、采用軟件渲染的D3DDEVTYPE_REF、不需要軟硬件支持的D3DDEVTYPE_NULLREF,或是采用要進行渲染工作的可插拔軟件的D3DDEVTYPE_SW。軟件渲染標識符允許運行Direct3D程序,它可以使用硬件不支持的特性。軟件渲染存在的問題是渲染速度慢,尤其是在開發游戲時。
下一參數hFocusWindow也是一個窗口句柄。參數BehaviorFlags是標識符組合,用于指定設備的運行方式。
pPresentationParameter是一個指針,它指向該函數前面創建的D3DPRESENT_PARAMTERS結構。ppReturnedDeviceInterface是一個指針,它指向新創建的Direct3D設備對象。如果該對象為NULL(空),或是函數返回除D3D_OK以外的值,那么Direct3D設備的創建失敗。
一旦完成Direct3D的設置和創建,就可以隨意渲染屏幕。初始化階段的CreateDevice()函數中創建的設備對象可以完成Direct3D中的渲染工作。渲染屏幕開始先要清屏為指定的顏色,告知Direct3D將要開始繪制新場景,渲染想要渲染的物體,完成屏幕渲染,在屏幕上顯示渲染結果。代碼1.6給出了驗證這個過程的例子代碼。例子代碼創建簡單的顯示空白黑屏的函數。
在屏幕上繪制一個空白屏的代碼:
- void RenderScene()
- {
- // Clear the backbuffer.
- g_D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET,
- D3DCOLOR_XRGB(0,0,0), 1.0f, 0);
- // Begin the scene. Start rendering.
- g_D3DDevice->BeginScene();
- // End the scene. Stop rendering.
- g_D3DDevice->EndScene();
- // Display the scene.
- g_D3DDevice->Present(NULL, NULL, NULL, NULL);
- }
RenderScene()函數開始先清除后臺緩存。調用Direct3D設備對象的Clear()函數可以完成該工作。Clear()函數的參數包括:要清除的矩形數目(0代表清除整個屏幕)、定義想要清除的屏幕區域矩形鏈表(NULL代表整個屏幕)、標識要清除內容的標識符、清除后的顏色、要設定的深度值、設定模板緩存值。對標識符參數而言,D3DCLEAR_DEFAULT清除所有的渲染目標,D3DCLEAR_STENCIL清除模板緩存,而D3DCLEAR_ZBUFFER清除深度緩存。后面將會更多地介紹深度緩存。
一旦完成清除工作,渲染函數將調用設備對象的BeginScene()函數,在Direct3D中啟動一個新場景。在Direct3D中渲染任何圖形前,都必須先調用BeginScene()函數。一旦渲染完要渲染的物體,就調用設備對象的EndScene()函數結束渲染。記住:每個BeginScene()函數必須有一個與之對應的EndScene()函數。由于這里只是繪制了一個空白窗口,所以在BeginScene()和EndScene()之間不需要添加任何代碼。
最后一步是在屏幕上顯示渲染結果。調用設備對象的Present()函數可以完成顯示。就目前的學習而言,Present()函數的參數可以全部設為NULL(空)。第一個參數是正在顯示的原始矩形,如果不使用交換鏈,那么該值必須為NULL(空)。第二個參數是一個指針,它指向要渲染的最終矩形。第三個參數是正在顯示的窗口的窗口句柄。另外,由于沒有用到交換鏈,所以對正在使用的窗口句柄而言,該值設為NULL(空)。這個正在使用的窗口句柄是在Direct3D初始化過程中為D3DPRESENT_PARAMETERS對象設置的窗口句柄。Present()函數中的最后一個參數是緩存區域,它代表需要更新的最小區域。同樣,該參數涉及到交換鏈,也可以設為NULL(空)。
既然可以使用Direct3D初始化和渲染屏幕,那么剩下要做的工作是在退出程序時,釋放對象。在Direct3D中,會發現通常要在退出程序前釋放系統使用的內存,從而避免內存泄漏。所有要釋放的內存都可以通過調用對象的Release()函數釋放。Release()函數會減少對象的引用計數。如果引用計數降為0,那么系統就可以安全地從內存中刪除對象。如果對單個對象有多個引用,那么必須牢記對所有的對象都要調用Release()函數,否則將不會釋放內存。要牢記的規則就是:如果創建了對象,那么最終就要釋放該對象。下述代碼給出了在一個名為Shutdown()的函數中釋放兩個Direct3D對象的方法。
釋放所有的Direct3D對象的代碼
- void Shutdown()
- {
- if(g_D3DDevice != NULL) g_D3DDevice->Release();
- if(g_D3D != NULL) g_D3D->Release();
- g_D3DDevice = NULL;
- g_D3D = NULL;
- }
到這里,基本的模塊都已經一目了然了,下面我們把他串聯起來,構成一個整體。
完整的Blank Window演示程序代碼如下:
- #include<d3d9.h>
- #pragma comment(lib, "d3d9.lib")
- #pragma comment(lib, "d3dx9.lib")
- #define WINDOW_CLASS "UGPDX"
- #define WINDOW_NAME "Blank D3D Window"
- // Function Prototypes...
- bool InitializeD3D(HWND hWnd, bool fullscreen);
- void RenderScene();
- void Shutdown();
- // Direct3D object and device.
- LPDIRECT3D9 g_D3D = NULL;
- LPDIRECT3DDEVICE9 g_D3DDevice = NULL;
- LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- switch(msg)
- {
- case WM_DESTROY:
- PostQuitMessage(0);
- return 0;
- break;
- case WM_KEYUP:
- if(wParam == VK_ESCAPE) PostQuitMessage(0);
- break;
- }
- return DefWindowProc(hWnd, msg, wParam, lParam);
- }
- int WINAPI WinMain(HINSTANCE hInst, HINSTANCE prevhInst, LPSTR cmdLine, 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
- HWND hWnd = CreateWindow(WINDOW_CLASS, WINDOW_NAME, WS_OVERLAPPEDWINDOW,
- 100, 100, 640, 480, GetDesktopWindow(), NULL,
- wc.hInstance, NULL);
- // Initialize Direct3D
- if(InitializeD3D(hWnd, false))
- {
- // Show the window
- ShowWindow(hWnd, SW_SHOWDEFAULT);
- UpdateWindow(hWnd);
- // Enter the message loop
- MSG msg;
- ZeroMemory(&msg, sizeof(msg));
- while(msg.message != WM_QUIT)
- {
- if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- else
- RenderScene();
- }
- }
- // Release any and all resources.
- Shutdown();
- // Unregister our window.
- UnregisterClass(WINDOW_CLASS, wc.hInstance);
- return 0;
- }
- bool InitializeD3D(HWND hWnd, bool fullscreen)
- {
- D3DDISPLAYMODE displayMode;
- // Create the D3D object.
- g_D3D = Direct3DCreate9(D3D_SDK_VERSION);
- if(g_D3D == NULL) return false;
- // Get the desktop display mode.
- if(FAILED(g_D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode)))
- return false;
- // Set up the structure used to create the D3DDevice
- D3DPRESENT_PARAMETERS d3dpp;
- ZeroMemory(&d3dpp, sizeof(d3dpp));
- if(fullscreen)
- {
- d3dpp.Windowed = FALSE;
- d3dpp.BackBufferWidth = 640;
- d3dpp.BackBufferHeight = 480;
- }
- else
- d3dpp.Windowed = TRUE;
- d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
- d3dpp.BackBufferFormat = displayMode.Format;
- // Create the D3DDevice
- if(FAILED(g_D3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
- D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_D3DDevice)))
- {
- return false;
- }
- return true;
- }
- void RenderScene()
- {
- // Clear the backbuffer.
- g_D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0);
- // Begin the scene. Start rendering.
- g_D3DDevice->BeginScene();
- // End the scene. Stop rendering.
- g_D3DDevice->EndScene();
- // Display the scene.
- g_D3DDevice->Present(NULL, NULL, NULL, NULL);
- }
- void Shutdown()
- {
- if(g_D3DDevice != NULL) g_D3DDevice->Release();
- if(g_D3D != NULL) g_D3D->Release();
- }
只要成功安裝了DirectX SDK,并配置好DirectX的開發環境,則萬事俱備。
我們先編譯該程序,然后運行它。我們可以看到一個640×480分辨率的空白窗口。
下面給出了運行后的窗口截圖:
以上就是本節筆記的全部內容。
本節源代碼請點擊這里下載:【Visual C++】Code_Note_2
請大家繼續關注【 Visual C++】游戲開發筆記系列,謝謝大家一直的支持~~~
The end
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。