Direct3D初始化
Direct3D初始化步骤(核心代码):
1 // 描述交换链 2 DXGI_SWAP_CHAIN_DESC sd; 3 sd.BufferDesc.Width = mClientWidth; 4 sd.BufferDesc.Height = mClientHeigth; 5 sd.BufferDesc.RefreshRate.Numerator = 60; 6 sd.BufferDesc.RefreshRate.Denominator = 1; 7 sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 8 sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; 9 sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; 10 sd.SampleDesc.Count = 1; // 多重采样数量和质量级别 11 sd.SampleDesc.Quality = 0; 12 sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // 将它用作渲染目标 13 sd.BufferCount = 1; 14 sd.OutputWindow = mhMainWnd; 15 sd.Windowed = true; 16 sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; 17 sd.Flags = 0; 18 19 UINT createDeviceFlags = 0; 20 // 创建设备和交换链 21 D3D10CreateDeviceAndSwapChain(0, md3dDriverType, 0, createDeviceFlags, 22 D3D10_SDK_VERSION, &sd, &mSwapChain, &md3dDevice); 23 24 // 创建渲染目标视图 25 ID3D10Texture2D* backBuffer; 26 mSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), reinterpret_cast<void**>(&backBuffer)); 27 md3dDevice->CreateRenderTargetView(backBuffer, 0, &mRenderTargetView); 28 backBuffer->Release();//每调用一次IDXGISwapChain::GetBuffer,后台缓冲区的COM引用计数向上递增一次,所以释放 29 30 // 创建深度/模板缓冲区及其视图 31 D3D10_TEXTURE2D_DESC depthStencilDesc; 32 depthStencilDesc.Width = mClientWidth; 33 depthStencilDesc.Height = mClientHeigth; 34 depthStencilDesc.MipLevels = 1; 35 depthStencilDesc.ArraySize = 1; 36 depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; 37 depthStencilDesc.SampleDesc.Count = 1; 38 depthStencilDesc.SampleDesc.Quality = 0; 39 depthStencilDesc.Usage = D3D10_USAGE_DEFAULT; 40 depthStencilDesc.BindFlags = D3D10_BIND_DEPTH_STENCIL; 41 depthStencilDesc.CPUAccessFlags = 0; 42 depthStencilDesc.MiscFlags = 0; 43 md3dDevice->CreateTexture2D(&depthStencilDesc, 0, &mDepthStencilBuffer); 44 md3dDevice->CreateDepthStencilView(mDepthStencilBuffer, 0, &mDepthStencilView); 45 46 // 将视图绑定到输出合并器阶段 47 md3dDevice->OMSetRenderTargets(1, &mRenderTargetView, mDepthStencilView); 48 49 // 设置视口 50 // 通过修改视口,可以把3D场景渲染到后台缓冲区的一个子矩形区域中 51 D3D10_VIEWPORT vp; 52 vp.TopLeftX = 0; 53 vp.TopLeftY = 0; 54 vp.Width = mClientWidth; 55 vp.Height = mClientHeigth; 56 vp.MinDepth = 0.0f; 57 vp.MaxDepth = 1.0f; 58 md3dDevice->RSSetViewports(1, &vp);
本程序中,使用md3dDevice::ClearRenderTargetView清除渲染目标视图的颜色缓冲区,设为特定的颜色,然后调用mSwapChain->Present(0, 0)函数在屏幕上显示渲染缓冲区的内容(即设定的背景颜色)。
完整程序(使用类):
1 /* 2 2015.4 3 DirectX10 Init 4 5 对 Direct3D 进行初始化 6 1. 填充一个DXGI_SWAP_CHAIN_DESC结构体,该结构体描述了所要创建的交换链的特性。 7 2. 使用D3D10CreateDeviceAndSwapChain 函数创建ID3D10Device接口和IDXGISwapChain接口。 8 3. 为交换链的后台缓冲区创建一个渲染目标视图。 9 4. 创建深度/模板缓冲区以及相关的深度/模板视图。 10 5. 将渲染目标视图和深度/模板视图绑定到渲染管线的输出合并阶段,使它们可以被Direct3D使用。 11 6. 设置视口。 12 */ 13 14 #include <iostream> 15 #include <string> 16 #include <d3d10.h> 17 #include <d3dx10.h> 18 19 #pragma comment(lib, "d3d10.lib") 20 #pragma comment(lib, "d3dx10.lib") 21 22 LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); 23 24 class D3DApp 25 { 26 public: 27 D3DApp(HINSTANCE hInstance); 28 ~D3DApp(); 29 30 HINSTANCE getAppInstance(); 31 HWND getMainWnd(); 32 int run(); 33 34 void initApp(); 35 void onResize(); 36 void updateScene(); 37 void drawScene(); 38 LRESULT msgProc(UINT msg, WPARAM wParam, LPARAM lParam); 39 40 protected: 41 void initMainWindow(); 42 void initDirect3D(); 43 44 HINSTANCE mhAppInstance; 45 HWND mhMainWnd; 46 bool mAppPaused; 47 bool mMinimized; 48 bool mMaximized; 49 bool mResizing; 50 51 std::wstring mFrameStatus; 52 std::wstring mMainWndCaption; 53 54 ID3D10Device* md3dDevice; 55 IDXGISwapChain* mSwapChain; 56 D3D10_DRIVER_TYPE md3dDriverType; 57 D3DXCOLOR mClearColor; 58 ID3D10Texture2D* mDepthStencilBuffer; 59 ID3D10RenderTargetView* mRenderTargetView; 60 ID3D10DepthStencilView* mDepthStencilView; 61 ID3DX10Font* mFont; 62 63 int mClientWidth; 64 int mClientHeigth; 65 }; 66 67 D3DApp::D3DApp(HINSTANCE hInstance) 68 { 69 mhAppInstance = hInstance; 70 mhMainWnd = 0; 71 mAppPaused = false; 72 mMinimized = false; 73 mMaximized = false; 74 mResizing = false; 75 76 mFrameStatus = L""; 77 mMainWndCaption = L"D3D10 Application"; 78 79 md3dDevice = 0; 80 mSwapChain = 0; 81 md3dDriverType = D3D10_DRIVER_TYPE_HARDWARE; 82 mClearColor = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f); 83 mFont = 0; 84 mClientWidth = 800; 85 mClientHeigth = 600; 86 } 87 88 D3DApp::~D3DApp() 89 { 90 mSwapChain->Release(); 91 mFont->Release(); 92 md3dDevice->Release(); 93 } 94 95 HINSTANCE D3DApp::getAppInstance() 96 { 97 return mhAppInstance; 98 } 99 100 HWND D3DApp::getMainWnd() 101 { 102 return mhMainWnd; 103 } 104 105 int D3DApp::run() 106 { 107 MSG msg = { 0 }; 108 109 while (msg.message != WM_QUIT) 110 { 111 if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) 112 { 113 TranslateMessage(&msg); 114 DispatchMessage(&msg); 115 } 116 else 117 { 118 drawScene(); 119 } 120 } 121 return (int)msg.wParam; 122 } 123 124 void D3DApp::initApp() 125 { 126 initMainWindow(); 127 initDirect3D(); 128 129 D3DX10_FONT_DESC fontDesc; 130 fontDesc.Height = 24; 131 fontDesc.Width = 0; 132 fontDesc.Weight = 0; 133 fontDesc.MipLevels = 1; 134 fontDesc.Italic = false; //非斜体 135 fontDesc.CharSet = DEFAULT_CHARSET; 136 fontDesc.OutputPrecision = OUT_DEFAULT_PRECIS; 137 fontDesc.Quality = DEFAULT_QUALITY; 138 fontDesc.PitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; 139 wcscpy_s(fontDesc.FaceName, L"Times New Roman"); 140 141 D3DX10CreateFontIndirect(md3dDevice, &fontDesc, &mFont); 142 } 143 144 void D3DApp::onResize() 145 { 146 // Release the old views, as they hold references to the buffers we 147 // will be destroying. Also release the old depth/stencil buffer. 148 mRenderTargetView->Release(); 149 mDepthStencilBuffer->Release(); 150 mDepthStencilView->Release(); 151 152 // Resize the swap chain and recreate the render target view. 153 mSwapChain->ResizeBuffers(1, mClientWidth, mClientHeigth, DXGI_FORMAT_R8G8B8A8_UNORM, 0); //[0, 1]区间 154 155 // 创建渲染目标视图 156 ID3D10Texture2D* backBuffer; 157 mSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), reinterpret_cast<void**>(&backBuffer)); 158 md3dDevice->CreateRenderTargetView(backBuffer, 0, &mRenderTargetView); 159 backBuffer->Release(); 160 161 // 创建深度/模板缓冲区及其视图 162 D3D10_TEXTURE2D_DESC depthStencilDesc; 163 depthStencilDesc.Width = mClientWidth; 164 depthStencilDesc.Height = mClientHeigth; 165 depthStencilDesc.MipLevels = 1; 166 depthStencilDesc.ArraySize = 1; 167 depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; 168 depthStencilDesc.SampleDesc.Count = 1; 169 depthStencilDesc.SampleDesc.Quality = 0; 170 depthStencilDesc.Usage = D3D10_USAGE_DEFAULT; 171 depthStencilDesc.BindFlags = D3D10_BIND_DEPTH_STENCIL; 172 depthStencilDesc.CPUAccessFlags = 0; 173 depthStencilDesc.MiscFlags = 0; 174 md3dDevice->CreateTexture2D(&depthStencilDesc, 0, &mDepthStencilBuffer); 175 md3dDevice->CreateDepthStencilView(mDepthStencilBuffer, 0, &mDepthStencilView); 176 177 // 将视图绑定到输出合并器阶段,使它们可以被Direct3D使用 178 md3dDevice->OMSetRenderTargets(1, &mRenderTargetView, mDepthStencilView); 179 180 // 设置视口 181 D3D10_VIEWPORT vp; 182 vp.TopLeftX = 0; 183 vp.TopLeftY = 0; 184 vp.Width = mClientWidth; 185 vp.Height = mClientHeigth; 186 vp.MinDepth = 0.0f; 187 vp.MaxDepth = 1.0f; 188 md3dDevice->RSSetViewports(1, &vp); 189 } 190 191 void D3DApp::updateScene() 192 { 193 194 } 195 196 void D3DApp::drawScene() 197 { 198 mClearColor = D3DXCOLOR(0.0f, 0.5f, 0.0f, 1.0f); 199 200 // 清除渲染目标视图的颜色缓冲区,设为特定的颜色 201 md3dDevice->ClearRenderTargetView(mRenderTargetView, mClearColor); 202 203 // 调用交换链的Present函数在屏幕上显示渲染缓冲区的内容 204 mSwapChain->Present(0, 0); 205 } 206 207 LRESULT D3DApp::msgProc(UINT msg, WPARAM wParam, LPARAM lParam) 208 { 209 switch (msg) 210 { 211 case WM_DESTROY: 212 PostQuitMessage(0); 213 return 0; 214 } 215 return DefWindowProc(mhMainWnd, msg, wParam, lParam); 216 } 217 218 void D3DApp::initMainWindow() 219 { 220 WNDCLASS wc; 221 wc.style = CS_HREDRAW | CS_VREDRAW; 222 wc.lpfnWndProc = MainWndProc; 223 wc.cbClsExtra = 0; 224 wc.cbWndExtra = 0; 225 wc.hInstance = mhAppInstance; 226 wc.hIcon = LoadIcon(0, IDI_APPLICATION); 227 wc.hCursor = LoadCursor(0, IDC_ARROW); 228 wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); 229 wc.lpszMenuName = 0; 230 wc.lpszClassName = L"D3DWndClassName"; 231 232 if (!RegisterClass(&wc)) 233 { 234 MessageBox(0, L"RegisterClass FAILED", 0, 0); 235 PostQuitMessage(0); 236 } 237 RECT R = { 0, 0, mClientWidth, mClientHeigth }; 238 AdjustWindowRect(&R, WS_OVERLAPPEDWINDOW, false); 239 int width = R.right - R.left; 240 int height = R.bottom - R.top; 241 242 mhMainWnd = CreateWindow(L"D3DWndClassName", mMainWndCaption.c_str(), 243 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, 0, 0, mhAppInstance, this); 244 if (!mhMainWnd) 245 { 246 MessageBox(0, L"CreateWindow FAILED", 0, 0); 247 PostQuitMessage(0); 248 } 249 250 ShowWindow(mhMainWnd, SW_SHOW); 251 UpdateWindow(mhMainWnd); 252 } 253 254 void D3DApp::initDirect3D() 255 { 256 // 描述交换链 257 DXGI_SWAP_CHAIN_DESC sd; 258 sd.BufferDesc.Width = mClientWidth; 259 sd.BufferDesc.Height = mClientHeigth; 260 sd.BufferDesc.RefreshRate.Numerator = 60; 261 sd.BufferDesc.RefreshRate.Denominator = 1; 262 sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 263 sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; 264 sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; 265 sd.SampleDesc.Count = 1; // 多重采样数量和质量级别 266 sd.SampleDesc.Quality = 0; 267 sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // 将它用作渲染目标 268 sd.BufferCount = 1; 269 sd.OutputWindow = mhMainWnd; 270 sd.Windowed = true; 271 sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; 272 sd.Flags = 0; 273 274 UINT createDeviceFlags = 0; 275 // 创建设备和交换链 276 D3D10CreateDeviceAndSwapChain(0, md3dDriverType, 0, createDeviceFlags, 277 D3D10_SDK_VERSION, &sd, &mSwapChain, &md3dDevice); 278 279 //onResize(); //在该程序中可以使用此句代替下面语句 280 281 // 创建渲染目标视图 282 ID3D10Texture2D* backBuffer; 283 mSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), reinterpret_cast<void**>(&backBuffer)); 284 md3dDevice->CreateRenderTargetView(backBuffer, 0, &mRenderTargetView); 285 backBuffer->Release();//每调用一次IDXGISwapChain::GetBuffer,后台缓冲区的COM引用计数向上递增一次,所以释放 286 287 // 创建深度/模板缓冲区及其视图 288 D3D10_TEXTURE2D_DESC depthStencilDesc; 289 depthStencilDesc.Width = mClientWidth; 290 depthStencilDesc.Height = mClientHeigth; 291 depthStencilDesc.MipLevels = 1; 292 depthStencilDesc.ArraySize = 1; 293 depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; 294 depthStencilDesc.SampleDesc.Count = 1; 295 depthStencilDesc.SampleDesc.Quality = 0; 296 depthStencilDesc.Usage = D3D10_USAGE_DEFAULT; 297 depthStencilDesc.BindFlags = D3D10_BIND_DEPTH_STENCIL; 298 depthStencilDesc.CPUAccessFlags = 0; 299 depthStencilDesc.MiscFlags = 0; 300 md3dDevice->CreateTexture2D(&depthStencilDesc, 0, &mDepthStencilBuffer); 301 md3dDevice->CreateDepthStencilView(mDepthStencilBuffer, 0, &mDepthStencilView); 302 303 // 将视图绑定到输出合并器阶段 304 md3dDevice->OMSetRenderTargets(1, &mRenderTargetView, mDepthStencilView); 305 306 // 设置视口 307 // 通过修改视口,可以把3D场景渲染到后台缓冲区的一个子矩形区域中 308 D3D10_VIEWPORT vp; 309 vp.TopLeftX = 0; 310 vp.TopLeftY = 0; 311 vp.Width = mClientWidth; 312 vp.Height = mClientHeigth; 313 vp.MinDepth = 0.0f; 314 vp.MaxDepth = 1.0f; 315 md3dDevice->RSSetViewports(1, &vp); 316 317 } 318 319 LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 320 { 321 static D3DApp* app = 0; 322 switch (msg) 323 { 324 case WM_CREATE: 325 { 326 // CREATESTRUCT结构定义了应用程序中窗口过程的初始化参数 327 CREATESTRUCT* cs = (CREATESTRUCT*)lParam; 328 app = (D3DApp*)cs->lpCreateParams; 329 return 0; 330 } 331 } 332 333 if (app) 334 return app->msgProc(msg, wParam, lParam); 335 else 336 return DefWindowProc(hwnd, msg, wParam, lParam); 337 } 338 339 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd) 340 { 341 D3DApp theApp(hInstance); 342 343 theApp.initApp(); 344 theApp.run(); 345 346 return 0; 347 }