學習DirectX9中Direct3D的用法。
一。初始化
1. 創建Direct3D的藉口指針。
IDirect3D9* g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
2. 獲得顯示模式後,創建device。
D3DDISPLAYMODE d3ddm;
g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);
D3DPRESENT_PARAMETERS d3dpp; // Direct3D的參數
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE; // 設置爲window模式
d3dpp.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC; //設置切換效果
d3dpp.BackBufferFormat = d3ddm.Format; // 根據取得的顯示模式,設置格式
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL; // 定義Device指針
g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDevice)
二。 描畫
1. 清空畫面。
g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); //清空整個畫面,背景顏色爲黑色
HRESULT Clear(
DWORD Count, // pRects指向的RECT數目 const D3DRECT *pRects, // 指向RECT列表,表示要清除的各個矩形。 DWORD Flags, // 定義清除方法。 D3DCOLOR Color, // 清除後的顏色 float Z, // 清除後的Z座標[0,1] DWORD Stencil // 清除後的模板值。 ); // 返回D3D_OK表示成功,else 失敗
2. 開始描畫
g_pD3DDevice->BeginScene(); // 開始
// 中間的描畫
g_pD3DDevice->EndScene(); // 結束
g_pD3DDevice->Present(NULL, NULL, NULL, NULL); //顯示下一個緩存的畫面
HRESULT Present(
CONST RECT *pSourceRect, // 指明源矩形 CONST RECT *pDestRect, // 指明目的矩形 HWND hDestWindowOverride, // 指明目的窗口 CONST RGNDATA *pDirtyRegion // 指明需要刷新的區域 );
三。結束
if (g_pD3DDevice!=NULL) { g_pD3DDevice->Release(); g_pD3DDevice = NULL; }
if (g_pD3D!= NULL) { g_pD3D->Release(); g_pD3D = NULL; }
下面是一個簡單的畫一個三角形的程序,我區分了directx8和9的代碼,用宏_GY_D3D8。代碼主要是從一本書上copy來的。
#include "stdafx.h" #ifdef _GY_D3D8 #include < d3d8.h > #else #include < d3d9.h > #endif #ifdef _GY_D3D8 LPDIRECT3D8 g_pD3D = NULL; LPDIRECT3DDEVICE8 g_pD3DDevice = NULL; LPDIRECT3DVERTEXBUFFER8 g_pVertexBuffer = NULL; #else LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pD3DDevice = NULL; LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer = NULL; #endif struct CUSTOMVERTEX { FLOAT x, y, z, rhw; DWORD color; }; #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) #define SafeRelease(pObject) / if (pObject != NULL) {/ pObject->Release(); / pObject = NULL; / } HRESULT InitializeD3D(HWND hWnd) { #ifdef _GY_D3D8 g_pD3D = Direct3DCreate8(D3D_SDK_VERSION); #else g_pD3D = Direct3DCreate9(D3D_SDK_VERSION); #endif if (g_pD3D == NULL) { return E_FAIL; } D3DDISPLAYMODE d3ddm; if (FAILED( g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) { return E_FAIL; } D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; #ifdef _GY_D3D8 d3dpp.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC; #else d3dpp.SwapEffect = D3DSWAPEFFECT_COPY; #endif d3dpp.BackBufferFormat = d3ddm.Format; if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDevice))) { return E_FAIL; } return S_OK; } HRESULT InitialiseVertexBuffer() { VOID* pVertex; CUSTOMVERTEX cvVertex[] = { {250.0f, 100.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(255,0,0) }, {400.0f, 350.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(0,255,0) }, {100.0f, 350.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(0,0,255) } }; #ifdef _GY_D3D8 if (FAILED(g_pD3DDevice->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVertexBuffer))) { return E_FAIL; } if (FAILED(g_pVertexBuffer->Lock(0, sizeof(cvVertex), (BYTE**)&pVertex, 0))) { return E_FAIL; } #else if (FAILED(g_pD3DDevice->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVertexBuffer, NULL))) { return E_FAIL; } if (FAILED(g_pVertexBuffer->Lock(0, sizeof(cvVertex), (void**)&pVertex, 0))) { return E_FAIL; } #endif memcpy(pVertex, cvVertex, sizeof(cvVertex)); g_pVertexBuffer->Unlock(); return S_OK; } void Render() { if (g_pD3DDevice == NULL) { return; } // background color g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); g_pD3DDevice->BeginScene(); #ifdef _GY_D3D8 g_pD3DDevice->SetStreamSource(0, g_pVertexBuffer, sizeof(CUSTOMVERTEX)); g_pD3DDevice->SetVertexShader(D3DFVF_CUSTOMVERTEX); #else g_pD3DDevice->SetStreamSource(0, g_pVertexBuffer, 0, sizeof(CUSTOMVERTEX)); g_pD3DDevice->SetFVF(D3DFVF_CUSTOMVERTEX); #endif g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1); g_pD3DDevice->EndScene(); g_pD3DDevice->Present(NULL, NULL, NULL, NULL); } void CleanUp() { SafeRelease(g_pVertexBuffer); SafeRelease(g_pD3DDevice); SafeRelease(g_pD3D); } void GameLoop() { MSG msg; BOOL fMessage; PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE); while(msg.message != WM_QUIT) { fMessage = PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE); if (fMessage) { TranslateMessage(&msg); DispatchMessage(&msg); }else { Render(); } } } LRESULT WINAPI WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_DESTROY: PostQuitMessage(0); return 0; break; case WM_KEYUP: switch(wParam) { case VK_ESCAPE: DestroyWindow(hWnd); return 0; break; } break; default: break; } return DefWindowProc(hWnd, msg, wParam, lParam); } INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE , LPSTR , int ) { WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, WinProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, "DX Project 1", NULL}; RegisterClassEx(&wc); HWND hWnd = CreateWindow("DX Project 1", "www.andypike.com: Tutorial 1", WS_OVERLAPPEDWINDOW, 50, 50, 500, 500, GetDesktopWindow(), NULL, wc.hInstance, NULL); if(SUCCEEDED(InitializeD3D(hWnd))) { //Show our window ShowWindow(hWnd, SW_SHOWDEFAULT); UpdateWindow(hWnd); //Start game running: Enter the game loop if (SUCCEEDED(InitialiseVertexBuffer())) { GameLoop(); } } CleanUp(); UnregisterClass("DX Project 1", wc.hInstance); return 0; }