1. main.cpp文件
#include <windows.h>
#include <d3d11.h>
#include <DirectXColors.h>
#include <d3dcompiler.h>
using namespace DirectX;
HINSTANCE g_hInstance = nullptr;
HWND g_hWnd = nullptr;
LPCWSTR g_name = L"D3D11Demo";
D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL; //驱动类型
D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0; //特征等级
ID3D11Device *g_pd3dDevice = nullptr; //设备
ID3D11DeviceContext *g_pImmediateContext = nullptr; //设备上下文
IDXGISwapChain *g_pSwapChain = nullptr; //交换链
ID3D11RenderTargetView *g_pRenderTargetView = nullptr; //要创建的视图
ID3D11VertexShader *g_pVertexShader = nullptr; //顶点着色器
ID3D11PixelShader *g_pPixelShader = nullptr; //像素着色器
ID3D11InputLayout *g_pVertexLayout = nullptr; //输入布局(顶点布局)
ID3D11Buffer *g_pVertexBuffer = nullptr; //D3D11缓冲区
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, nullptr, 0, 0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else//渲染
{
Render();
}
}
CleanupDevice();
return (int)msg.wParam;
}
HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow)
{
WNDCLASSEX wcex;
wcex.cbClsExtra = 0;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.cbWndExtra = 0;
wcex.hbrBackground = (HBRUSH)COLOR_WINDOWFRAME;
wcex.hCursor = LoadCursor(nullptr,IDC_ARROW);
wcex.hIcon = LoadIcon(nullptr, IDI_WINLOGO);
wcex.hIconSm = wcex.hIcon;
wcex.hInstance = hInstance;
wcex.lpfnWndProc = WndProc;
wcex.lpszClassName = g_name;
wcex.lpszMenuName = nullptr;
wcex.style = CS_HREDRAW | CS_VREDRAW;
if (!RegisterClassEx(&wcex))
return E_FAIL;
g_hInstance = hInstance;
RECT rc = {0, 0, 800, 800};
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, nullptr, nullptr, g_hInstance, nullptr);
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 CompileShaderFromFile(WCHAR * szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob ** ppBlobOut)
{
HRESULT hr = S_OK;
DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#ifdef _DEBUG
// Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.
// Setting this flag improves the shader debugging experience, but still allows
// the shaders to be optimized and to run exactly the way they will run in
// the release configuration of this program.
dwShaderFlags |= D3DCOMPILE_DEBUG;
// Disable optimizations to further improve shader debugging
dwShaderFlags |= D3DCOMPILE_SKIP_OPTIMIZATION;
#endif
ID3DBlob* pErrorBlob = nullptr;
hr = D3DCompileFromFile( szFileName, nullptr, nullptr, szEntryPoint, szShaderModel,
dwShaderFlags, 0, ppBlobOut, &pErrorBlob );
if( FAILED(hr) )
{
if( pErrorBlob )
{
OutputDebugStringA( reinterpret_cast<const char*>( pErrorBlob->GetBufferPointer() ) );
pErrorBlob->Release();
}
return hr;
}
if( pErrorBlob ) pErrorBlob->Release();
return S_OK;
}
//创建设备及交换链
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;//创建标志,0用于游戏发布,一般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; //采样等级,Count = 1, Quality = 0禁止了重采样
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; //常用参数
sd.Windowed = TRUE; //是否全屏
for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; ++driverTypeIndex)
{
g_driverType = driverTypes[driverTypeIndex];
hResult = D3D11CreateDeviceAndSwapChain(
nullptr, //默认图形适配器
g_driverType, //驱动类型
nullptr, //实现软件渲染设备的动态库句柄,如果使用的驱动设备类型是软件设备则不能为nullptr
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 = nullptr;
//获取后缓冲区地址
hResult = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
if (FAILED(hResult))
return hResult;
//创建目标视图
hResult = g_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_pRenderTargetView);
//释放后缓冲
pBackBuffer->Release();
if (FAILED(hResult))
return hResult;
//绑定到渲染管线
g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, nullptr);
//设置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);
// Compile the vertex shader
ID3DBlob *pVSBlob = nullptr;
hResult = CompileShaderFromFile(L"sample.fx", "VS", "vs_4_0", &pVSBlob);
if( FAILED(hResult) )
{
MessageBox( nullptr,
L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
return hResult;
}
// Create the vertex shader
hResult = g_pd3dDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), nullptr, &g_pVertexShader);
if (FAILED(hResult))
{
pVSBlob->Release();
return hResult;
}
// Define the input layout
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
UINT numElements = ARRAYSIZE(layout);
// Create the input layout传递到设备了
hResult = g_pd3dDevice->CreateInputLayout(layout, numElements, pVSBlob->GetBufferPointer(),
pVSBlob->GetBufferSize(), &g_pVertexLayout);
pVSBlob->Release();
if (FAILED(hResult))
{
return hResult;
}
// Set the input layout
g_pImmediateContext->IASetInputLayout(g_pVertexLayout);// 激活layout
// Compile the pixel shader
ID3DBlob *pPSBlob = nullptr;
hResult = CompileShaderFromFile(L"sample.fx", "PS", "ps_4_0", &pPSBlob);
if( FAILED( hResult ) )
{
MessageBox( nullptr,
L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
return hResult;
}
// Create the pixel shader
hResult = g_pd3dDevice->CreatePixelShader(pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), nullptr, &g_pPixelShader);
pPSBlob->Release();
if (FAILED(hResult))
{
return hResult;
}
// Create vertex buffer
struct SimpleVertex
{
XMFLOAT3 Pos;
};
SimpleVertex vertices[] =
{
XMFLOAT3( -0.25f, 0.25f, 0.5f ),
XMFLOAT3( 0.25f, 0.25f, 0.5f ),
XMFLOAT3( -0.25f, -0.25f, 0.5f ),
XMFLOAT3( 0.25f, -0.25f, 0.5f ),
};
D3D11_BUFFER_DESC bd;
ZeroMemory( &bd, sizeof(bd) );
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof( SimpleVertex ) * 4;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
D3D11_SUBRESOURCE_DATA InitData;
ZeroMemory( &InitData, sizeof(InitData) );
InitData.pSysMem = vertices;
hResult = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer );
if( FAILED( hResult) )
return hResult;
// Set vertex buffer设置成被激活的顶点缓冲
UINT stride = sizeof( SimpleVertex );
UINT offset = 0;
g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset );
// Set primitive topology
g_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP );
return S_OK;
}
void Render()
{
g_pImmediateContext->ClearRenderTargetView(g_pRenderTargetView, DirectX::Colors::White);// float ClearColor[4] = { 0.5f, 0.1f, 0.2f, 1.0f }; //red,green,blue,alpha
// TODO:
g_pImmediateContext->VSSetShader(g_pVertexShader, nullptr, 0);
g_pImmediateContext->PSSetShader(g_pPixelShader, nullptr, 0);
g_pImmediateContext->Draw(4, 0);
g_pSwapChain->Present(0, 0);
}
void CleanupDevice()
{
if (g_pVertexBuffer)
g_pVertexBuffer->Release();
if (g_pVertexShader)
g_pVertexShader->Release();
if (g_pPixelShader)
g_pPixelShader->Release();
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();
}
2. fx文件(编译时需要在属性配置中设置为“从生成中排除”)
//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
float4 VS( float4 Pos : POSITION ) : SV_POSITION
{
return Pos;
}
//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 PS( float4 Pos : SV_POSITION ) : SV_Target
{
return float4( 0.0f, 0.0f, 0.0f, 1.0f ); // Yellow, with Alpha = 1
}
3. 参考
官方:https://msdn.microsoft.com/en-us/library/windows/apps/ff729719.aspx
翻译:http://blog.youkuaiyun.com/jake2012/article/details/24367525