#ifndef _D3DX_BASE_H_
#define _D3DX_BASE_H_
#include<d3d11.h>
#include<d3dx11.h>
#include<DxErr.h>
class D3DXBase{
public:
D3DXBase();
virtual ~D3DXBase();
bool Initialize(HINSTANCE hInstance,HWND hwnd);
void Shutdown();
virtual bool LoadContent();
virtual void UnloadContent();
virtual void Update(float dt) = 0;
virtual void Render() = 0;
protected:
HINSTANCE hInstance_;
HWND hwnd_;
D3D_DRIVER_TYPE driverType_;
D3D_FEATURE_LEVEL featureLevel_;
ID3D11Device *d3dDevice_;
ID3D11DeviceContext *d3dContext_;
IDXGISwapChain *swapChain_;
ID3D11RenderTargetView *backBufferTarget_;
};
#endif
D3DX.cpp
#include"D3DX.h"
D3DXBase::D3DXBase():driverType_(D3D_DRIVER_TYPE_NULL),featureLevel_(D3D_FEATURE_LEVEL_11_0),d3dDevice_(0),d3dContext_(0),swapChain_(0),backBufferTarget_(0){}
D3DXBase::~D3DXBase(){
Shutdown();
}
bool D3DXBase::LoadContent(){
return true;
}
void D3DXBase::UnloadContent(){
}
void D3DXBase::Shutdown(){
UnloadContent();
if(backBufferTarget_)backBufferTarget_->Release();
if(swapChain_)swapChain_->Release();
if(d3dContext_)d3dContext_->Release();
if(d3dDevice_)d3dDevice_->Release();
backBufferTarget_ = 0;
swapChain_ = 0;
d3dContext_ = 0;
d3dDevice_ = 0;
}
bool D3DXBase::Initialize(HINSTANCE hInstance,HWND hwnd){
hInstance_ = hInstance;
hwnd_ = hwnd;
RECT dimensions;
GetClientRect(hwnd,&dimensions);
unsigned int width = dimensions.right - dimensions.left;
unsigned int height = dimensions.bottom - dimensions.top;
D3D_DRIVER_TYPE driverTypes[] = {
D3D_DRIVER_TYPE_HARDWARE,D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE,D3D_DRIVER_TYPE_SOFTWARE
};
unsigned int totalDriverTypes = ARRAYSIZE(driverTypes);
D3D_FEATURE_LEVEL featureLevels[] = {
//D3D_FEATURE_LEVEL_11_1,//not supported
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_1,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_3
};
unsigned int totalFeatureLevels = ARRAYSIZE(featureLevels);
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc,sizeof(swapChainDesc));
swapChainDesc.BufferCount = 1;
swapChainDesc.BufferDesc.Width = width;
swapChainDesc.BufferDesc.Height = height;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.OutputWindow = hwnd;
swapChainDesc.Windowed = true;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
//swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;//让显卡驱动程序选择最高效的显示模式。
//swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;//那么当应用程序切换到全屏模式时,Direct3D会自动选择与当前的后台缓冲区设置最匹配的显示模式。如果未指定该标志值,那么当应用程序切换到全屏模式时,Direct3D会使用当前的桌面显示模式。我们在示例框架中没有使用该标志值,因为对于我们的演示程序来说,在全屏模式下使用当前的桌面显示模式可以得到很好的效果。
unsigned int creationFlags = 0;
#ifdef _DEBUG
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
HRESULT result;
unsigned int driver = 0;
//创建Dx设备上下文,dx设备和交换链(IDXGISwapChain)
for(driver = 0;driver < totalDriverTypes ; ++driver){
result = D3D11CreateDeviceAndSwapChain(0,driverTypes[driver],0,creationFlags,featureLevels,totalFeatureLevels,D3D11_SDK_VERSION,&swapChainDesc,&swapChain_,&d3dDevice_,&featureLevel_,&d3dContext_);
if(SUCCEEDED(result)){
driverType_ = driverTypes[driver];
break;
}
}
if(FAILED(result)){
DXTRACE_MSG("Failed to create the Direct3D device!");
return false;
}
//缓存纹理
ID3D11Texture2D *backBufferTexture;
result = swapChain_->GetBuffer(0,_uuidof(ID3D11Texture2D),(LPVOID*)&backBufferTexture);
if(FAILED(result)){
DXTRACE_MSG("Failed to get the swap chain back buffer!");
return false;
}
//目标视图
result = d3dDevice_ -> CreateRenderTargetView(backBufferTexture,0,&backBufferTarget_);
if(backBufferTexture){
backBufferTexture -> Release();
}
if(FAILED(result)){
DXTRACE_MSG("Failed to create the render target view!");
return false;
}
//渲染目标
d3dContext_->OMSetRenderTargets(1,&backBufferTarget_,0);
//视口
D3D11_VIEWPORT viewport;
viewport.Width = static_cast<float>(width);
viewport.Height = static_cast<float>(height);
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
//设置视口
d3dContext_->RSSetViewports(1,&viewport);
return LoadContent();
}
D3DX11Demo.h
#ifndef _BLACK_DEMO_H_
#define _BLACK_DEMO_H_
#include"D3DX.h"
class BlankDemo:public D3DXBase{
public:
BlankDemo();
virtual ~BlankDemo();
bool LoadContent();
void UnloadContent();
void Update(float dt);
void Render();
private:
float updateColor_;
};
#endif
D3DX11Demo.cpp
#include"D3DX11Demo.h"
BlankDemo::BlankDemo():updateColor_(0.0f){
}
BlankDemo::~BlankDemo(){
}
bool BlankDemo::LoadContent(){
return true;
}
void BlankDemo::UnloadContent(){
}
void BlankDemo::Update(float dt){
updateColor_ = dt;
}
void BlankDemo::Render(){
if(d3dContext_ == 0){
return;
}
float clearColor[4] = {updateColor_,0.5f,0.5f,1.0f};
d3dContext_->ClearRenderTargetView(backBufferTarget_,clearColor);
swapChain_->Present(0,0);
}
windows.cpp
#include<windows.h>
#include<memory>
#include"D3DX11Demo.h"
#pragma comment(lib,"gdi32.lib")
#pragma comment(lib,"user32.lib")
#pragma comment(lib,"kernel32.lib")
#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"d3dx11.lib")
#pragma comment(lib,"DxErr.lib")
#pragma comment(lib,"D3DX.lib")//user-defined linking D3DX.cpp to lib
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR cmdLine,int nShow){
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(cmdLine);
WNDCLASSEX wndClass = {0};
wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.hInstance = hInstance;
wndClass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = "DX11BookWinddowClass";
if(!RegisterClassEx(&wndClass)){
return -1;
}
RECT rc = {0,0,640,480};
AdjustWindowRect(&rc,WS_OVERLAPPEDWINDOW,false);
HWND hwnd = CreateWindow("DX11BookWinddowClass","Blank Win32 Window",WS_OVERLAPPEDWINDOW,0,0,rc.right-rc.left,rc.bottom-rc.top,NULL,NULL,hInstance,NULL);
if(!hwnd)return -1;
ShowWindow(hwnd,nShow);
std::auto_ptr<D3DXBase> demo(new BlankDemo());
bool result = demo->Initialize(hInstance,hwnd);
if(result == false){
return -1;
}
MSG msg = {0};
while(msg.message != WM_QUIT){
if(PeekMessage(&msg,0,0,0,PM_REMOVE)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else{
demo->Update(0.35f);
demo->Render();
UpdateWindow(hwnd);
}
}
demo->Shutdown();
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam){
PAINTSTRUCT ps;
HDC hdc;
switch(message){
case WM_PAINT:
hdc = BeginPaint(hwnd,&ps);
EndPaint(hwnd,&ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd,message,wParam,lParam);
}
return 0;
}