原文:
Directx11学习笔记【八】 龙书D3DApp的实现
directx11龙书中的初始化程序D3DApp跟我们上次写的初始化程序大体一致,只是包含了计时器的内容,而且使用了深度模板缓冲。
D3DUtil类,定义了一些工具和宏,目前只定义了两个宏,以后还会添加
#ifndef D3DUTIL_H #define D3DUTIL_H #include <d3dx11.h> #include <xnamath.h> #include <dxerr.h> #include <cassert> //------------------------------- //方便检测d3d errors //------------------------------- #if defined(DEBUG) | defined(_DEBUG) #ifndef HR #define HR(x) \ { \ HRESULT hr = (x); \ if (FAILED(hr)) \ { \ DXTrace(__FILE__, (DWORD)__LINE__, hr, L#x, true); \ } \ } #endif #else #ifndef HR #define HR(x) (x) #endif #endif //------------------------------ //方便删除COM objects //------------------------------ #define ReleaseCOM(x) { if(x){ x->Release(); x = 0; } } #endif//D3DUTIL_H
基类D3DApp的实现
.h文件
1 #ifndef D3DAPP_H 2 #define D3DAPP_H 3 4 #include <windows.h> 5 #include <string> 6 #include "D3DUtil.h" 7 #include "GameTimer.h" 8 9 class D3DApp 10 { 11 public: 12 D3DApp(HINSTANCE hInstance); 13 virtual ~D3DApp(); 14 15 HINSTANCE AppInst() const; 16 HWND MainWnd() const; 17 float AspectRatio() const; 18 19 int Run(); 20 21 virtual bool Init(); 22 virtual void OnResize(); 23 virtual void UpdateScene(float dt) = 0; 24 virtual void DrawScene(); 25 virtual LRESULT MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 26 27 //鼠标事件 28 virtual void OnMouseDown(WPARAM btnState, int x, int y){} 29 virtual void OnMouseUp(WPARAM btnState, int x, int y){} 30 virtual void OnMouseMove(WPARAM btnState, int x, int y){} 31 32 protected: 33 bool InitMainWindow(); 34 bool InitDirect3D(); 35 //计算FPS 36 void CalculateFrameStats(); 37 38 protected: 39 HINSTANCE m_hAppInst; //实例句柄 40 HWND m_hMainWnd; //主窗口句柄 41 bool m_isAppPaused; 42 bool m_isMinimized; 43 bool m_isMaximized; 44 bool m_isResizing; 45 UINT m_4xMsaaQuality; //4重采样质量 46 47 GameTimer m_timer; //计时器 48 D3D_DRIVER_TYPE m_d3dDriverType; //驱动类型 49 ID3D11Device *m_pD3dDevice; //设备 50 ID3D11DeviceContext *m_pImmediateContext; //设备上下文 51 IDXGISwapChain *m_pSwapChain; //交换链 52 ID3D11Texture2D *m_pDepthStencilBuffer; //深度模板缓冲 53 ID3D11RenderTargetView *m_pRenderTargetView; //渲染目标视图 54 ID3D11DepthStencilView *m_pDepthStencilView; //深度模板缓冲视图 55 D3D11_VIEWPORT m_screenViewPort; //视口 56 57 std::wstring m_mainWndCaption; //窗口标题 58 int m_clientWidth; 59 int m_clientHeight; 60 bool m_isEnable4xMsaa; //是否支持4重采样 61 }; 62 #endif //D3DAPP_H
.cpp
1 #include <windowsx.h>//包含大量可用的宏和各种方便的工具 2 #include <sstream> 3 #include "D3DApp.h" 4 5 namespace 6 { 7 D3DApp *g_d3dApp = NULL; 8 } 9 10 LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 11 { 12 return g_d3dApp->MsgProc(hWnd,msg,wParam,lParam); 13 } 14 15 16 D3DApp::D3DApp(HINSTANCE hInstance) : 17 m_hAppInst(hInstance), 18 m_mainWndCaption(L"D3D11 Application"), 19 m_d3dDriverType(D3D_DRIVER_TYPE_HARDWARE), 20 m_clientHeight(600), 21 m_clientWidth(800), 22 m_isEnable4xMsaa(false), 23 m_hMainWnd(NULL), 24 m_isAppPaused(false), 25 m_isMaximized(false), 26 m_isMinimized(false), 27 m_isResizing(false), 28 m_4xMsaaQuality(0), 29 30 m_pD3dDevice(NULL), 31 m_pImmediateContext(NULL), 32 m_pSwapChain(NULL), 33 m_pRenderTargetView(NULL), 34 m_pDepthStencilBuffer(NULL) 35 { 36 ZeroMemory(&m_screenViewPort, sizeof(D3D11_VIEWPORT)); 37 g_d3dApp = this; 38 } 39 40 D3DApp::~D3DApp() 41 { 42 ReleaseCOM(m_pRenderTargetView); 43 ReleaseCOM(m_pDepthStencilBuffer); 44 ReleaseCOM(m_pSwapChain); 45 ReleaseCOM(m_pDepthStencilView); 46 47 if (m_pImmediateContext) 48 m_pImmediateContext->ClearState(); 49 50 ReleaseCOM(m_pImmediateContext); 51 ReleaseCOM(m_pD3dDevice); 52 } 53 54 HINSTANCE D3DApp::AppInst() const 55 { 56 return m_hAppInst; 57 } 58 59 HWND D3DApp::MainWnd() const 60 { 61 return m_hMainWnd; 62 } 63 64 float D3DApp::AspectRatio() const 65 { 66 return static_cast<float>(m_clientWidth / m_clientHeight); 67 } 68 69 int D3DApp::Run() 70 { 71 MSG msg; 72 ZeroMemory(&msg, sizeof(MSG)); 73 m_timer.Reset(); 74 75 while (msg.message != WM_QUIT) 76 { 77 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 78 { 79 TranslateMessage(&msg); 80 DispatchMessage(&msg); 81 } 82 else 83 { 84 m_timer.Tick(); 85 if (!m_isAppPaused) 86 { 87 CalculateFrameStats(); 88 UpdateScene(m_timer.DeltaTime()); 89 DrawScene(); 90 } 91 else 92 { 93 Sleep(100); 94 } 95 } 96 } 97 return static_cast<int>(msg.wParam); 98 } 99 100 bool D3DApp::Init() 101 { 102 if (!InitMainWindow()) 103 return false; 104 if (!InitDirect3D()) 105 return false; 106 return true; 107 } 108 109 void D3DApp::OnResize() 110 { 111 assert(m_pImmediateContext); 112 assert(m_pD3dDevice); 113 assert(m_pSwapChain); 114 115 //release old views 116 ReleaseCOM(m_pRenderTargetView); 117 ReleaseCOM(m_pDepthStencilView); 118 ReleaseCOM(m_pDepthStencilBuffer); 119 120 HR(m_pSwapChain->ResizeBuffers(1, m_clientWidth, m_clientHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0)); 121 ID3D11Texture2D *backBuffer; 122 HR(m_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer))); 123 HR(m_pD3dDevice->CreateRenderTargetView(backBuffer, 0, &m_pRenderTargetView)); 124 ReleaseCOM(backBuffer); 125 126 //create depth/stencil buffer and view 127 D3D11_TEXTURE2D_DESC depthStencilDecs; 128 depthStencilDecs.Width = m_clientWidth; 129 depthStencilDecs.Height = m_clientHeight; 130 depthStencilDecs.MipLevels = 1; 131 depthStencilDecs.ArraySize = 1; 132 depthStencilDecs.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; 133 134 //是否使用4重采样 135 if (m_isEnable4xMsaa) 136 { 137 depthStencilDecs.SampleDesc.Count = 4; 138 depthStencilDecs.SampleDesc.Quality = m_4xMsaaQuality - 1; 139 } 140 else 141 { 142 depthStencilDecs.SampleDesc.Count = 1; 143 depthStencilDecs.SampleDesc.Quality = 0; 144 } 145 146 depthStencilDecs.Usage = D3D11_USAGE_DEFAULT; 147 depthStencilDecs.BindFlags = D3D11_BIND_DEPTH_STENCIL; 148 depthStencilDecs.CPUAccessFlags = 0; 149 depthStencilDecs.MiscFlags = 0; 150 151 HR(m_pD3dDevice->CreateTexture2D(&depthStencilDecs, 0, &m_pDepthStencilBuffer)); 152 HR(m_pD3dDevice->CreateDepthStencilView(m_pDepthStencilBuffer, 0, &m_pDepthStencilView)); 153 154 //绑定新的render target view 和 depth/stencil view到管线 155 m_pImmediateContext->OMSetRenderTargets(1, &m_pRenderTargetView, m_pDepthStencilView); 156 157 //设置viewport 158 m_screenViewPort.TopLeftX = 0; 159 m_screenViewPort.TopLeftY = 0; 160 m_screenViewPort.Width = m_clientWidth; 161 m_screenViewPort.Height = m_clientHeight; 162 m_screenViewPort.MaxDepth = 1.0f; 163 m_screenViewPort.MinDepth = 0.0f; 164 165 m_pImmediateContext->RSSetViewports(1, &m_screenViewPort); 166 } 167 168 LRESULT D3DApp::MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 169 { 170 switch (msg) 171 { 172 //当一个窗口被激活或失去激活状态 173 case WM_ACTIVATE: 174 if (LOWORD(wParam) == WA_INACTIVE) 175 { 176 m_isAppPaused = true; 177 m_timer.Stop(); 178 } 179 else 180 { 181 m_isAppPaused = false; 182 m_timer.Start(); 183 } 184 return 0; 185 186 //当用户重绘窗口时 187 case WM_SIZE: 188 m_clientWidth = LOWORD(lParam); 189 m_clientHeight = HIWORD(lParam); 190 if (m_pD3dDevice) 191 { 192 if (wParam == SIZE_MINIMIZED)//窗口最小化 193 { 194 m_isAppPaused = true; 195 m_isMinimized = true; 196 m_isMaximized = true; 197 } 198 else if (wParam == SIZE_MAXIMIZED)//窗口最大化 199 { 200 m_isAppPaused = false; 201 m_isMinimized = false; 202 m_isMaximized = true; 203 OnResize(); 204 } 205 else if (wParam == SIZE_RESTORED)//窗口大小改变既不是最大化也不是最小化 206 { 207 if (m_isMinimized) 208 { 209 m_isAppPaused = false; 210 m_isMinimized = false; 211 OnResize(); 212 } 213 else if (m_isMaximized) 214 { 215 m_isAppPaused = false; 216 m_isMaximized = false; 217 OnResize(); 218 } 219 //当用户正在改变窗口大小时不调用OnResize(),当改变完成后再 220 //调用 221 else if (m_isResizing) 222 { 223 224 } 225 else 226 { 227 OnResize(); 228 } 229 } 230 } 231 return 0; 232 233 //用户开始拖拽改变窗口大小 234 case WM_ENTERSIZEMOVE: 235 m_isAppPaused = true; 236 m_isResizing = true; 237 m_timer.Stop(); 238 return 0; 239 240 //用户改变窗口大小完毕 241 case WM_EXITSIZEMOVE: 242 m_isAppPaused = false; 243 m_isResizing = false; 244 m_timer.Start(); 245 OnResize(); 246 return 0; 247 //窗口销毁 248 case WM_DESTROY: 249 PostQuitMessage(0); 250 return 0; 251 252 //The WM_MENUCHAR message is sent when a menu is active and the user presses 253 // a key that does not correspond to any mnemonic or accelerator key. 254 case WM_MENUCHAR: 255 return MAKELRESULT(0, MNC_CLOSE); 256 257 //防止窗口变得太小 258 case WM_GETMINMAXINFO: 259 ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 200; 260 ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 200; 261 return 0; 262 263 case WM_LBUTTONDOWN: 264 case WM_MBUTTONDOWN: 265 case WM_RBUTTONDOWN: 266 OnMouseDown(wParam, GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)); 267 return 0; 268 case WM_LBUTTONUP: 269 case WM_MBUTTONUP: 270 case WM_RBUTTONUP: 271 OnMouseUp(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); 272 return 0; 273 case WM_MOUSEMOVE: 274 OnMouseMove(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); 275 return 0; 276 } 277 return DefWindowProc(hWnd, msg, wParam, lParam); 278 } 279 280 bool D3DApp::InitMainWindow() 281 { 282 WNDCLASS wc; 283 wc.cbClsExtra = 0; 284 wc.cbWndExtra = 0; 285 wc.hbrBackground = static_cast<HBRUSH>(GetStockObject(NULL_BRUSH)); 286 wc.hCursor = LoadCursor(0, IDC_ARROW); 287 wc.hIcon = LoadIcon(0, IDI_APPLICATION); 288 wc.hInstance = m_hAppInst; 289 wc.lpfnWndProc = MainWndProc; 290 wc.lpszClassName = L"D3DWndClassName"; 291 wc.lpszMenuName = NULL; 292 wc.style = CS_HREDRAW | CS_VREDRAW; 293 if (!RegisterClass(&wc)) 294 { 295 MessageBox(0, L"RegisterClass Failed", 0, 0); 296 return false; 297 } 298 299 RECT rect{ 0, 0, m_clientWidth, m_clientHeight }; 300 AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, false); 301 int width = rect.right - rect.left; 302 int height = rect.bottom - rect.top; 303 304 m_hMainWnd = CreateWindow(L"D3DWndClassName", m_mainWndCaption.c_str(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 305 width, height, NULL, NULL, m_hAppInst, 0); 306 if (!m_hMainWnd) 307 { 308 MessageBox(0, L"CreateWindow Failed", 0, 0); 309 return 0; 310 } 311 312 ShowWindow(m_hMainWnd,SW_SHOW); 313 UpdateWindow(m_hMainWnd); 314 315 return true; 316 } 317 318 bool D3DApp::InitDirect3D() 319 { 320 UINT createDeviceFlags = 0; 321 #if defined(DEBUG) || defined(_DEBUG) 322 createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; 323 #endif 324 325 D3D_FEATURE_LEVEL featureLevel; 326 HRESULT hr = D3D11CreateDevice( 327 0,//默认的adapter 328 m_d3dDriverType, 329 0, 330 createDeviceFlags, 331 0, 0, 332 D3D11_SDK_VERSION, 333 &m_pD3dDevice, 334 &featureLevel, 335 &m_pImmediateContext 336 ); 337 if (FAILED(hr)) 338 { 339 MessageBox(0, L"D3D11CreateDevice Failed", 0, 0); 340 return hr; 341 } 342 343 if (featureLevel != D3D_FEATURE_LEVEL_11_0) 344 { 345 MessageBox(0, L"Direct3D Feature Level 11 unsupported!", 0, 0); 346 return false; 347 } 348 349 //check 4x msaa quality support 350 HR(m_pD3dDevice->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m_4xMsaaQuality)); 351 assert(m_4xMsaaQuality > 0); 352 353 //填充交换链描述 354 DXGI_SWAP_CHAIN_DESC sd; 355 sd.BufferDesc.Width = m_clientWidth; 356 sd.BufferDesc.Height = m_clientHeight; 357 sd.BufferDesc.RefreshRate.Numerator = 60; 358 sd.BufferDesc.RefreshRate.Denominator = 1; 359 sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 360 sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; 361 sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; 362 //是否用4重采样 363 if (m_isEnable4xMsaa) 364 { 365 sd.SampleDesc.Count = 4; 366 sd.SampleDesc.Quality = m_4xMsaaQuality - 1; 367 } 368 else 369 { 370 sd.SampleDesc.Count = 1; 371 sd.SampleDesc.Quality = 0; 372 } 373 374 sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 375 sd.BufferCount = 1; 376 sd.OutputWindow = m_hMainWnd; 377 sd.Windowed = true; 378 sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; 379 sd.Flags = 0; 380 381 //要创建交换链必须得到IDXGIFactory 382 IDXGIDevice *pDxgiDevice = 0; 383 HR(m_pD3dDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&pDxgiDevice))); 384 385 IDXGIAdapter *pDxgiAdapter = 0; 386 HR(pDxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&pDxgiAdapter))); 387 388 IDXGIFactory *pDxgiFactory = 0; 389 HR(pDxgiAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&pDxgiFactory))); 390 391 HR(pDxgiFactory->CreateSwapChain(m_pD3dDevice, &sd, &m_pSwapChain)); 392 393 ReleaseCOM(pDxgiDevice); 394 ReleaseCOM(pDxgiAdapter); 395 ReleaseCOM(pDxgiFactory); 396 397 OnResize(); 398 399 return true; 400 } 401 402 void D3DApp::CalculateFrameStats() 403 { 404 //计算fps,每一帧调用 405 static int frameCnt = 0; 406 static float timeElapsed = 0.0f; 407 408 frameCnt++; 409 410 if ((m_timer.TotalTime() - timeElapsed) >= 1.0f) 411 { 412 float fps = static_cast<float>(frameCnt); 413 float mspf = 1000.f / fps; 414 415 std::wostringstream outs; 416 outs.precision(6);//浮点数显示6位 417 outs << m_mainWndCaption << L" " << L"FPS:" << fps << L" " 418 << L"Frame Time:" << mspf << L" (ms) "; 419 SetWindowText(m_hMainWnd, outs.str().c_str()); 420 421 frameCnt = 0; 422 timeElapsed += 1.0f; 423 } 424 } 425 426 void D3DApp::DrawScene() 427 { 428 429 }
初始化程序
InitDirect3DApp.h
1 #ifndef INITDIRECT3DAPP_H 2 #define INITDIRECT3DAPP_H 3 4 #include "D3DApp.h" 5 6 class InitDirect3DApp : public D3DApp 7 { 8 public: 9 InitDirect3DApp(HINSTANCE hInstance); 10 ~InitDirect3DApp(); 11 12 bool Init(); 13 void OnResize(); 14 void UpdateScene(float dt); 15 void DrawScene(); 16 }; 17 18 #endif//INITDIRECT3DAPP_H
InitDirect3DApp.cpp
1 #include "InitDirect3DApp.h" 2 3 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) 4 { 5 #if defined(DEBUG) | defined(_DEBUG) 6 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); 7 #endif 8 9 InitDirect3DApp theApp(hInstance); 10 11 if (!theApp.Init()) 12 return 0; 13 return theApp.Run(); 14 } 15 16 17 18 InitDirect3DApp::InitDirect3DApp(HINSTANCE hInstance) : D3DApp(hInstance) 19 { 20 } 21 22 InitDirect3DApp::~InitDirect3DApp() 23 { 24 } 25 26 bool InitDirect3DApp::Init() 27 { 28 if (!D3DApp::Init()) 29 return false; 30 return true; 31 } 32 33 void InitDirect3DApp::OnResize() 34 { 35 D3DApp::OnResize(); 36 } 37 38 void InitDirect3DApp::UpdateScene(float dt) 39 { 40 41 } 42 43 void InitDirect3DApp::DrawScene() 44 { 45 assert(m_pImmediateContext); 46 assert(m_pSwapChain); 47 48 float ClearColor[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; 49 m_pImmediateContext->ClearRenderTargetView(m_pRenderTargetView, ClearColor); 50 m_pImmediateContext->ClearDepthStencilView(m_pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); 51 HR(m_pSwapChain->Present(0, 0)); 52 }