Dx11DemoBase.h
#pragma once #include <d3d11.h> #include <D3DX11.h> #include <DxErr.h> #pragma comment(lib, "d3d11.lib") #pragma comment(lib, "d3dx11.lib") #pragma comment(lib, "dxerr.lib") class Dx11DemoBase { public: Dx11DemoBase(); virtual ~Dx11DemoBase(); bool Initialize(HINSTANCE hInstance, HWND hWnd); void ShutDown();//释放内存 virtual bool LoadContent();//载入具体的Demo自己的内容,如纹理,几何体,着色器 virtual void UnLoadContent();//释放具体Demo中的内容 virtual void Update(float dt) = 0; virtual void Render() = 0; protected: HINSTANCE m_hInstance; HWND m_hWnd; D3D_DRIVER_TYPE m_driverType; D3D_FEATURE_LEVEL m_featureLevel; ID3D11Device* m_pd3dDevice; ID3D11DeviceContext* m_pImmediateContext; IDXGISwapChain* m_pSwapChain; ID3D11RenderTargetView* m_pRenderTargetView; };
Dx11DemoBase.cpp
#include "Dx11DemoBase.h" Dx11DemoBase::Dx11DemoBase() :m_driverType(D3D_DRIVER_TYPE_NULL), m_featureLevel(D3D_FEATURE_LEVEL_11_0), m_pd3dDevice(NULL), m_pImmediateContext(NULL), m_pSwapChain(NULL), m_pRenderTargetView(NULL){} Dx11DemoBase::~Dx11DemoBase() { ShutDown(); } bool Dx11DemoBase::LoadContent() { return true; } void Dx11DemoBase::UnLoadContent() { } void Dx11DemoBase::ShutDown() { UnLoadContent(); if (m_pRenderTargetView) m_pRenderTargetView->Release(); if (m_pSwapChain) m_pSwapChain->Release(); if (m_pd3dDevice) m_pd3dDevice->Release(); if (m_pImmediateContext) m_pImmediateContext->Release(); m_pRenderTargetView = NULL; m_pSwapChain = NULL; m_pd3dDevice = NULL; m_pImmediateContext = NULL; } //初始化 bool Dx11DemoBase::Initialize(HINSTANCE hInstance, HWND hWnd) { HRESULT result; m_hInstance = hInstance; m_hWnd = hWnd; RECT rc; GetClientRect(m_hWnd, &rc); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; 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(sd)); sd.BufferCount = 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 = m_hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; sd.Windowed = true; UINT createDeviceFlags = 0; #ifdef _DEBUG createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; ++driverTypeIndex) { result = D3D11CreateDeviceAndSwapChain( NULL, driverTypes[driverTypeIndex], NULL, createDeviceFlags, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &sd, &m_pSwapChain, &m_pd3dDevice, &m_featureLevel, &m_pImmediateContext ); if (SUCCEEDED(result)) { m_driverType = driverTypes[driverTypeIndex]; break; } } if (FAILED(result)) { return result; } ID3D11Texture2D *pBackBuffer = NULL; result = m_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); if (FAILED(result)) { return result; } result = m_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &m_pRenderTargetView); if (pBackBuffer) pBackBuffer->Release(); if (FAILED(result)) { return result; } m_pImmediateContext->OMSetRenderTargets(1, &m_pRenderTargetView, NULL); D3D11_VIEWPORT vp; vp.Height = static_cast<float>(width);//用c++的static_cast转换类型是个好习惯 vp.Width = static_cast<float>(height); vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0.0f; vp.TopLeftY = 0.0f; m_pImmediateContext->RSSetViewports(1, &vp); return LoadContent(); }
BlankDemo.h
#pragma once #include "Dx11DemoBase.h" class BlankDemo : public Dx11DemoBase { public: BlankDemo(); virtual ~BlankDemo(); bool LoadContent(); void UnLoadContent(); void Update(float dt); void Render(); };
BlankDemo.cpp
#include "BlankDemo.h" BlankDemo::BlankDemo() { } BlankDemo::~BlankDemo() { } bool BlankDemo::LoadContent() { return true; } void BlankDemo::UnLoadContent() { } void BlankDemo::Update(float dt) { } void BlankDemo::Render() { if (!m_pImmediateContext) m_pImmediateContext = NULL; float clearColors[4] = { 0.0f, 0.0f, 0.5f, 1.0f }; m_pImmediateContext->ClearRenderTargetView(m_pRenderTargetView, clearColors); m_pSwapChain->Present(0, 0); }
main.cpp
#include <windows.h> #include <memory> #include "BlankDemo.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd) { WNDCLASSEX wcex; wcex.cbClsExtra = 0; wcex.cbSize = sizeof(wcex); wcex.cbWndExtra = 0; wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.hCursor = LoadCursor(NULL,IDC_ARROW); wcex.hIcon = LoadIcon(NULL, IDI_WINLOGO); wcex.hIconSm = wcex.hIcon; wcex.hInstance = hInstance; wcex.lpfnWndProc = WndProc; wcex.lpszClassName = L"BlankDemo"; wcex.lpszMenuName = L"BlankDemo"; wcex.style = CS_HREDRAW | CS_VREDRAW; if (!RegisterClassEx(&wcex)) return -1; RECT rc = { 0, 0, 800, 640 }; AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false); HWND hwnd = CreateWindowEx(WS_EX_APPWINDOW, L"BlankDemo", L"BlankDemo", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL); if (!hwnd) return -1; ShowWindow(hwnd, nShowCmd); std::auto_ptr<Dx11DemoBase> demo(new BlankDemo());//使用智能指针 bool result = demo->Initialize(hInstance, hwnd); if (!result) return -1; MSG msg; ZeroMemory(&msg, sizeof(msg)); while (msg.message != WM_QUIT) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } demo->Update(0.0f); demo->Render(); } demo->ShutDown(); return static_cast<int>(msg.wParam); } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT paintStruct; HDC hDc; switch (message) { case WM_PAINT: hDc = BeginPaint(hWnd, &paintStruct); EndPaint(hWnd, &paintStruct); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }