Windows API Programming
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <d3d11_1.h>
#include <d3dcompiler.h>
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d3dcompiler.lib")
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CLOSE:
PostQuitMessage(0);
return 0;
case WM_KEYDOWN:
if (wParam == VK_ESCAPE) {
PostQuitMessage(0);
}
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdShow, BOOL nCmdShow) {
HWND hwnd;
MSG msg;
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(wc));
wc.cbSize = sizeof(wc);
wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND+1;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = L"MY_CLASS";
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
hwnd = CreateWindow(L"MY_CLASS", L"DX11.1 Render Output Window", WS_OVERLAPPEDWINDOW, 15, 15, 1200, 1000, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, SW_SHOW);
do {
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
Sleep(2);
}
} while(true);
DestroyWindow(hwnd);
UnregisterClass(L"MY_CLASS", hInstance);
return (int)msg.wParam;
}
Enumerating Adapters and Creating the Device, Context, and Swap Chain
HRESULT result;
DXGI_SWAP_CHAIN_DESC1 swapChainDesc;
D3D_FEATURE_LEVEL afl, fl[] = { D3D_FEATURE_LEVEL_11_1 };
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.Stereo = FALSE;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 1;
IDXGIFactory2 *dxgiFactory;
IDXGIAdapter2 *dxgiAdapter;
vector<IDXGIAdapter2*> adapterList;
hresult = CreateDXGIFactory1(__uuidof(IDXGIFactory2), (void**)&dxgiFactory);
int i = 0;
while (dxgiFactory->EnumAdapters1(i++, (IDXGIAdapter1**)&dxgiAdapter) != DXGI_ERROR_NOT_FOUND)
{
adapterList.push_back(dxgiAdapter);
}
ID3D11Device *oldDevice;
ID3D11DeviceContext *oldContext;
hresult = D3D11CreateDevice(
adapterList[0],
D3D_DRIVER_TYPE_UNKNOWN,
NULL,
0,
fl,
ARRAYSIZE(fl),
D3D11_SDK_VERSION,
&oldDevice,
&afl,
&oldContext
);
if (FAILED(result)) {
return false;
}
ID3D11Device1 *newDevice;
ID3D11DeviceContext1 *newContext;
hresult = oldDevice->QueryInterface(__uuidof(ID3D11Device1), (void**)&newDevice);
if (FAILED(hresult)) {
return false;
}
hresult = oldContext->QueryInterface(__uuidof(ID3D11DeviceContext1), (void**)&newContext);
if (FAILED(hresult)) {
return false;
}
oldDevice->Release();
oldContext->Release();
IDXGISwapChain1 *swapChain;
hresult = dxgiFactory->CreateSwapChainForHwnd(newDevice, hwnd, &swapChainDesc, NULL, NULL, &swapChain);
if (FAILED(hresult)) {
return false;
}
dxgiFactory->Release();
for (i = 0;i < adapterList.size();i++) {
adapterList[i]->Release();
}
Creating The Default Vertex and Pixel Shader (HLSL)
cbuffer CB0 : register(cb0) {
matrix<float,4,4> transformMatrix;
}
struct a2v {
float3 pos : POSITION0;
float3 clr : COLOR0;
};
struct v2p {
float4 pos : SV_POSITION;
float4 clr : COLOR0;
};
v2p VS_Main(in a2v IN) {
v2p OUT;
OUT.pos = mul(transformMatrix, float4(IN.pos, 1.0f));
OUT.clr = float4(IN.clr, 1.0f);
return OUT;
}
float4 PS_Main(in v2p IN) : SV_TARGET {
return IN.clr;
}
Compiling The Shader and Laying Out Shader Data
ID3D11InputLayout *inputLayout;
D3D11_INPUT_ELEMENT_DESC inputElementDesc[] = {
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, sizeof(float)*3, D3D11_INPUT_PER_VERTEX_DATA, 0}
};
ID3D11VertexShader *vertexShader;
ID3DBlob *shaderBlob;
ID3DBlob *errorBlob;
hresult = D3DCompileFromFile(
L"defshader.hlsl",
NULL,
NULL,
"VS_Main",
"vs_5_0",
0,
0,
&shaderBlob,
&errorBlob
);
if (FAILED(hresult)) {
errorBlob->Release();
return false;
}
hresult = newDevice->CreateVertexShader(shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), 0, &vertexShader);
hresult = newDevice->CreateInputLayout(inputElementDesc, ARRAYSIZE(inputElementDesc), shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize, &inputLayout);
shaderBlob->Release();
ID3D11PixelShader *pixelShader;
hresult = D3DCompileFromFile(
L"defshader.hlsl",
NULL,
NULL,
"PS_Main",
"ps_5_0",
0,
0,
&shaderBlob,
&errorBlob
);
if (FAILED(hresult)) {
errorBlob->Release();
return false;
}
hresult = newDevice->CreatePixelShader(shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), 0, &pixelShader);
shaderBlob->Release();
newContext->IASetInputLayout(inputLayout);
inputLayout->Release();
newContext->VSSetShader(vertexShader, 0, 0);
newContext->PSSetShader(pixelShader, 0, 0);
vertexShader->Release();
pixelShader->Release();
Constant Buffer
D3D11_BUFFER_DESC matrixBufferDesc;
ID3D11Buffer *matrixBuffer;
ZeroMemory(&matrixBufferDesc, sizeof(matrixBufferDesc));
matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
matrixBufferDesc.ByteWidth = sizeof(float)*16;
matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
newDevice->CreateBuffer(&matrixBufferDesc, 0, &matrixBuffer);
newContext->VSSetConstantBuffers(0, 1, &matrixBuffer);
Updating The Constant Buffer
float newMatrix[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f };
D3D11_MAPPED_SUBRESOURCE msr;
newContext->Map(matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &msr);
memcpy(msr.pData, newMatrix, sizeof(float)*16);
if (0) {
float *matrixData = reinterpret_cast<float*>(msr.pData);
matrixData[0] = 1.0f;
matrixData[1] = 2.0f;
}
newContext->Unmap(matrixBuffer, 0);
Creating The Vertex Buffer
const float vertices[] = {
-0.5f, 0.0f, 2.0f, 1.0f, 1.0f, 0.0f,
0.0f, 0.5f, 3.0f, 1.0f, 0.0f, 1.0f,
0.5f, 0.0f, 2.0f, 0.0f, 1.0f, 0.0f,
0.0f, -0.5f, 3.0f, 0.3f, 0.2f, 0.7f,
-0.5f, 0.0f, 2.0f, 0.5f, 0.7f, 0.3f
};
D3D11_BUFFER_DESC bufferDesc;
D3D11_SUBRESOURCE_DATA bufferData;
ID3D11Buffer *vertexBuffer;
ZeroMemory(&bufferDesc, sizeof(bufferDesc));
ZeroMemory(&bufferData, sizeof(bufferData));
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufferDesc.ByteWidth = sizeof(float)*ARRAYSIZE(vertices);
bufferDesc.StructureByteStride = sizeof(float)*6;
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
bufferData.pSysMem = vertices;
newDevice->CreateBuffer(&bufferDesc, &bufferData, &vertexBuffer);
const UINT strides[] = { sizeof(float) * 6 };
const UINT offsets[] = { 0 };
newContext->IASetVertexBuffers(0, 1, &vertexBuffer, strides, offsets);
vertexBuffer->Release();
Resizing The Render Window
ID3D11RenderTargetView *view;
ID3D11Texture2D *viewBuffer;
D3D11_VIEWPORT vp;
newContext->OMSetRenderTargets(0, 0, 0);
swapChain->ResizeBuffers(1, newWidth, newHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0);
swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&viewBuffer);
newDevice->CreateRenderTargetView(viewBuffer, 0, &view);
viewBuffer->Release();
newContext->OMSetRenderTargets(1, &view, 0);
vp.Height = static_cast<FLOAT>(newHeight);
vp.Width = static_cast<FLOAT> (newWidth);
vp.MaxDepth = 1.0f;
vp.MinDepth = 0.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
newContext->RSSetViewports(1, &vp);
Rendering To The Output Window
FLOAT clearColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
newContext->ClearRenderTargetView(view, clearColor);
newContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
newContext->Draw(ARRAYSIZE(vertices)/6);
swapChain->Present(0, 0);