Directx11入門之D3D程式初始化
阿新 • • 發佈:2019-02-19
初始化的程式在書中第四章講解比較清楚,文章Directx11學習筆記【三】 第一個D3D11程式已經把書中內容做了大致翻譯,因此不再贅述。以下從原文複製了一些內容與整合後的程式碼。
在先前的解決方案中新建一個新的Win32專案FirstD3D11Demo。在寫程式碼之前,我們必須先新增dx11所需要的庫。為了連結dx庫,右鍵專案選擇屬性->vc++目錄,在包含目錄中新增你所安裝的SDK根目錄\Include,在庫目錄中新增 根目錄\lib\x86(或x64),在連結器->輸入的附加依賴項中新增d3d11.lib、d3dx11.lib、dxerr.lib。
#include <windows.h> #include <d3d11.h> #include <DxErr.h> #include <D3DX11.h> HINSTANCE g_hInstance = NULL; HWND g_hWnd = NULL; LPCWSTR g_name = L"FirstD3D11Demo"; D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL; //驅動型別 D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0; //特徵等級 ID3D11Device *g_pd3dDevice = NULL; //裝置 ID3D11DeviceContext *g_pImmediateContext = NULL; //裝置上下文 IDXGISwapChain *g_pSwapChain = NULL; //交換鏈 ID3D11RenderTargetView *g_pRenderTargetView = NULL; //要建立的檢視 HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow); HRESULT InitDevice(); void CleanupDevice(); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void Render(); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd) { if (FAILED(InitWindow(hInstance, nShowCmd))) return 0; if (FAILED(InitDevice())) { CleanupDevice(); return 0; } MSG msg; ZeroMemory(&msg, sizeof(MSG)); while (msg.message != WM_QUIT) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else//渲染 { Render(); } } CleanupDevice(); return static_cast<int>(msg.wParam); } HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow) { WNDCLASSEX wcex; wcex.cbClsExtra = 0; wcex.cbSize = sizeof(WNDCLASSEX); wcex.cbWndExtra = 0; wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hIcon = LoadIcon(NULL, IDI_WINLOGO); wcex.hIconSm = wcex.hIcon; wcex.hInstance = hInstance; wcex.lpfnWndProc = WndProc; wcex.lpszClassName = g_name; wcex.lpszMenuName = NULL; wcex.style = CS_HREDRAW | CS_VREDRAW; if (!RegisterClassEx(&wcex)) return E_FAIL; g_hInstance = hInstance; RECT rc{ 0,0,640,480 }; AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); g_hWnd = CreateWindowEx(WS_EX_APPWINDOW, g_name, g_name, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, g_hInstance, NULL); if (!g_hWnd) return E_FAIL; ShowWindow(g_hWnd, nCmdShow); return S_OK; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wPararm, LPARAM lParam) { switch (message) { case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wPararm, lParam); } return 0; } //建立裝置及交換鏈 HRESULT InitDevice() { HRESULT hResult = S_OK;//返回結果 RECT rc; GetClientRect(g_hWnd, &rc);//獲取視窗客戶區大小 UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; UINT createDeviceFlags = 0; #ifdef _DEBUG createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif //驅動型別陣列 D3D_DRIVER_TYPE driverTypes[] = { D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP, D3D_DRIVER_TYPE_REFERENCE }; UINT numDriverTypes = ARRAYSIZE(driverTypes); //特徵級別陣列 D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0 }; UINT numFeatureLevels = ARRAYSIZE(featureLevels); //交換鏈 DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(DXGI_SWAP_CHAIN_DESC));//填充 sd.BufferCount = 1; //我們只建立一個後緩衝(雙緩衝)因此為1 sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = g_hWnd; sd.SampleDesc.Count = 1; //1重取樣 sd.SampleDesc.Quality = 0; //取樣等級 sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; //常用引數 sd.Windowed = TRUE; //是否全屏 for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; ++driverTypeIndex) { g_driverType = driverTypes[driverTypeIndex]; hResult = D3D11CreateDeviceAndSwapChain( NULL, //預設圖形介面卡 g_driverType, //驅動型別 NULL, //實現軟體渲染裝置的動態庫控制代碼,如果使用的驅動裝置型別是軟體裝置則不能為NULL createDeviceFlags, //建立標誌,0用於遊戲釋出,一般D3D11_CREATE_DEVICE_DEBUG允許我們建立可供除錯的裝置,在開發中比較有用 featureLevels, //特徵等級 numFeatureLevels, //特徵等級數量 D3D11_SDK_VERSION, //sdk版本號 &sd, &g_pSwapChain, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext ); if (SUCCEEDED(hResult)) break; } if (FAILED(hResult)) return hResult; //建立渲染目標檢視 ID3D11Texture2D *pBackBuffer = NULL; //獲取後緩衝區地址 hResult = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); if (FAILED(hResult)) return hResult; //建立目標檢視 hResult = g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_pRenderTargetView); //釋放後緩衝 pBackBuffer->Release(); if (FAILED(hResult)) return hResult; //繫結到渲染管線 g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, NULL); //設定viewport D3D11_VIEWPORT vp; vp.Height = (FLOAT)height; vp.Width = (FLOAT)width; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; g_pImmediateContext->RSSetViewports(1, &vp); return S_OK; } void Render() { float ClearColor[4] = { 0.5f, 0.1f, 0.2f, 1.0f }; //red,green,blue,alpha g_pImmediateContext->ClearRenderTargetView(g_pRenderTargetView, ClearColor); g_pSwapChain->Present(0, 0); } void CleanupDevice() { if (g_pImmediateContext) g_pImmediateContext->ClearState(); if (g_pSwapChain) g_pSwapChain->Release(); if (g_pRenderTargetView) g_pRenderTargetView->Release(); if (g_pImmediateContext) g_pImmediateContext->Release(); if (g_pd3dDevice) g_pd3dDevice->Release(); }