Getting Started with DirectX 11
Welcome to the DirectX 11 getting‑started guide. This article walks you through the steps required to set up a basic DirectX 11 project, compile and run a simple “Hello Triangle” sample, and explore resources for deeper learning.
Prerequisites
- Windows 10 (or later) SDK – download
- Visual Studio 2022 (Community or higher) – download
- C++ development workload installed (Desktop development with C++)
- Basic familiarity with C++ and graphics programming concepts
Creating the Project
- Open Visual Studio → Create a new project.
- Select
Win32 Project
, give it a name (e.g.,DX11HelloTriangle
), and click Next. - Choose Application Settings → Empty project → Finish.
- Right‑click the project → Manage NuGet Packages → search for
DirectXTK12
and install (optional for helper utilities).
Hello Triangle Sample
Copy the following source files into your project. The example creates a window, initializes DirectX 11, and renders a single colored triangle.
main.cpp
#include <windows.h>
#include <d3d11.h>
#include <d3dcompiler.h>
#include <directxmath.h>
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d3dcompiler.lib")
using namespace DirectX;
// Vertex structure
struct Vertex {
XMFLOAT3 position;
XMFLOAT4 color;
};
// Global declarations
HWND g_hWnd = nullptr;
ID3D11Device* g_pd3dDevice = nullptr;
ID3D11DeviceContext* g_pImmediateContext = nullptr;
IDXGISwapChain* g_pSwapChain = nullptr;
ID3D11RenderTargetView* g_pRenderTargetView = nullptr;
ID3D11InputLayout* g_pVertexLayout = nullptr;
ID3D11Buffer* g_pVertexBuffer = nullptr;
// Forward declarations
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HRESULT InitDevice();
void CleanupDevice();
void Render();
// Entry point
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow)
{
// Register class and create window
WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hInstance;
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.lpszClassName = L"DX11SampleClass";
RegisterClassEx(&wcex);
RECT rc = { 0, 0, 800, 600 };
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
g_hWnd = CreateWindowW(L"DX11SampleClass", L"DirectX 11 – Hello Triangle",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
rc.right - rc.left, rc.bottom - rc.top,
nullptr, nullptr, hInstance, nullptr);
ShowWindow(g_hWnd, nCmdShow);
if (FAILED(InitDevice())) {
CleanupDevice();
return 0;
}
// Main message loop
MSG 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;
}
// ---------------------------------------------------------------------------
// Initialize Direct3D
HRESULT InitDevice()
{
// Swap chain description
DXGI_SWAP_CHAIN_DESC sd = {};
sd.BufferCount = 1;
sd.BufferDesc.Width = 800;
sd.BufferDesc.Height = 600;
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;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
// Create device and swap chain
UINT createDeviceFlags = 0;
D3D_FEATURE_LEVEL featureLevel;
const D3D_FEATURE_LEVEL FeatureLevelsRequested[] = {
D3D_FEATURE_LEVEL_11_0,
};
HRESULT hr = D3D11CreateDeviceAndSwapChain(
nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags,
FeatureLevelsRequested, 1, D3D11_SDK_VERSION,
&sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel,
&g_pImmediateContext);
if (FAILED(hr)) return hr;
// Create render target view
ID3D11Texture2D* pBackBuffer = nullptr;
g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_pRenderTargetView);
pBackBuffer->Release();
g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, nullptr);
// Setup viewport
D3D11_VIEWPORT vp;
vp.Width = (FLOAT)800;
vp.Height = (FLOAT)600;
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;
const char* szVS = R"(
struct VS_INPUT {
float3 Pos : POSITION;
float4 Col : COLOR;
};
struct PS_INPUT {
float4 Pos : SV_POSITION;
float4 Col : COLOR;
};
PS_INPUT VSMain(VS_INPUT input) {
PS_INPUT output;
output.Pos = float4(input.Pos, 1.0);
output.Col = input.Col;
return output;
}
)";
D3DCompile(szVS, strlen(szVS), nullptr, nullptr, nullptr, "VSMain", "vs_5_0",
0, 0, &pVSBlob, nullptr);
ID3D11VertexShader* pVertexShader = nullptr;
g_pd3dDevice->CreateVertexShader(pVSBlob->GetBufferPointer(),
pVSBlob->GetBufferSize(),
nullptr, &pVertexShader);
g_pImmediateContext->VSSetShader(pVertexShader, nullptr, 0);
// Define input layout
D3D11_INPUT_ELEMENT_DESC layout[] = {
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,
D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12,
D3D11_INPUT_PER_VERTEX_DATA, 0},
};
g_pd3dDevice->CreateInputLayout(layout, 2,
pVSBlob->GetBufferPointer(),
pVSBlob->GetBufferSize(),
&g_pVertexLayout);
pVSBlob->Release();
g_pImmediateContext->IASetInputLayout(g_pVertexLayout);
// Compile the pixel shader
ID3DBlob* pPSBlob = nullptr;
const char* szPS = R"(
struct PS_INPUT {
float4 Pos : SV_POSITION;
float4 Col : COLOR;
};
float4 PSMain(PS_INPUT input) : SV_TARGET {
return input.Col;
}
)";
D3DCompile(szPS, strlen(szPS), nullptr, nullptr, nullptr, "PSMain",
"ps_5_0", 0, 0, &pPSBlob, nullptr);
ID3D11PixelShader* pPixelShader = nullptr;
g_pd3dDevice->CreatePixelShader(pPSBlob->GetBufferPointer(),
pPSBlob->GetBufferSize(),
nullptr, &pPixelShader);
g_pImmediateContext->PSSetShader(pPixelShader, nullptr, 0);
pPSBlob->Release();
// Create vertex buffer
Vertex vertices[] = {
{ XMFLOAT3( 0.0f, 0.5f, 0.0f), XMFLOAT4(1,0,0,1) },
{ XMFLOAT3( 0.5f, -0.5f, 0.0f), XMFLOAT4(0,1,0,1) },
{ XMFLOAT3(-0.5f, -0.5f, 0.0f), XMFLOAT4(0,0,1,1) },
};
D3D11_BUFFER_DESC bd = {};
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(Vertex) * 3;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
D3D11_SUBRESOURCE_DATA InitData = {};
InitData.pSysMem = vertices;
g_pd3dDevice->CreateBuffer(&bd, &InitData, &g_pVertexBuffer);
UINT stride = sizeof(Vertex);
UINT offset = 0;
g_pImmediateContext->IASetVertexBuffers(0, 1, &g_pVertexBuffer, &stride, &offset);
g_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
return S_OK;
}
// ---------------------------------------------------------------------------
// Clean up the objects we've created
void CleanupDevice()
{
if (g_pImmediateContext) g_pImmediateContext->ClearState();
if (g_pRenderTargetView) g_pRenderTargetView->Release();
if (g_pSwapChain) g_pSwapChain->Release();
if (g_pVertexBuffer) g_pVertexBuffer->Release();
if (g_pVertexLayout) g_pVertexLayout->Release();
if (g_pd3dDevice) g_pd3dDevice->Release();
if (g_pImmediateContext) g_pImmediateContext->Release();
}
// ---------------------------------------------------------------------------
// Render a single frame
void Render()
{
// Clear the back buffer
FLOAT ClearColor[4] = { 0.1f, 0.1f, 0.1f, 1.0f };
g_pImmediateContext->ClearRenderTargetView(g_pRenderTargetView, ClearColor);
// Draw the triangle
g_pImmediateContext->Draw(3, 0);
// Present the information rendered to the back buffer to the front buffer (the screen)
g_pSwapChain->Present(0, 0);
}
// ---------------------------------------------------------------------------
// Window procedure
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
ValidateRect(hWnd, nullptr);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
Build and Run
- Right‑click the project → Properties.
- Under Configuration Properties → Linker → Input, add
d3d11.lib;d3dcompiler.lib
to Additional Dependencies. - Set Subsystem →
Windows (/SUBSYSTEM:WINDOWS)
. - Apply → OK, then Build Solution.
- Run the executable (F5). You should see a window with a simple colored triangle.
Next Steps
- Explore the DirectX 11 API reference for detailed documentation on each interface.
- Follow the step‑by‑step tutorials covering textures, shaders, and advanced rendering techniques.
- Check out the official Direct3D 11 documentation for best practices and performance tips.