Windows API: Basic DirectX 11 (Direct3D) Example

See related: Windows API examples

Here is a basic example of using DirectX 11 to fill the client window with a random solid color when a timer event fires. See the DirectX screen saver for another DirectX 11 demo. This example does not really dig into the three dimensional.

// *********************************************************************
// *                                                                   *
// *                      EXAMPLE DIRECTX 11                           *
// *                                                                   *
// *  FILL CLIENT WINDOW WITH A RANDOM SOLID COLOR EVERY HALF SECOND.  *
// *                                                                   *
// *********************************************************************

#ifndef UNICODE
#define UNICODE
#endif

// DirectX 11 library (this line of code works with Visual Studio; for other compilers add the d3d11 library to the linker)
#pragma comment(lib, "d3d11")

#include <windows.h>
#include <d3d11.h>

// variables for DirectX
ID3D11Device* device = NULL;
ID3D11DeviceContext* deviceContext = NULL;
IDXGISwapChain* swapChain = NULL;
ID3D11RenderTargetView* renderTargetView = NULL;

FLOAT color[] = { 0.25, 0.25, 0.25, 0.0 };

// handle window messages
LRESULT WINAPI wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_TIMER:
		if (deviceContext & swapChain)
		{
			// fill with random color every time the timer fires
			color[0] = (rand() % 100) / 100.0;
			color[1] = (rand() % 100) / 100.0;
			color[2] = (rand() % 100) / 100.0;
			color[3] = 0.0;
			deviceContext->ClearRenderTargetView(renderTargetView, color);
			swapChain->Present(1, 0);
		}
		break;

	case WM_CLOSE:
		if (MessageBox(hwnd, L"Are you sure you want to close?", L"Confirm Close", MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2) == IDYES)
			DestroyWindow(hwnd);
		return 0;

	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;

	case WM_SIZE: // fires when window changes its size
		if(deviceContext & swapChain)
		{
			RECT rc;
			GetWindowRect(hwnd, &rc);

			D3D11_VIEWPORT viewport;
			viewport.MinDepth = 0;
			viewport.MaxDepth = 1;
			viewport.TopLeftX = 0;
			viewport.TopLeftY = 0;
			viewport.Width = rc.right - rc.left;
			viewport.Height = rc.bottom - rc.top;
			deviceContext->RSSetViewports(1u, &viewport);

			// fill with the random color when user resizes window so there is no voided areas
			deviceContext->ClearRenderTargetView(renderTargetView, color);
			swapChain->Present(1, 0);
		}
		break;
	}
	return DefWindowProc(hwnd, msg, wParam, lParam);
}


// start point
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	HWND hwnd;
	const wchar_t* windowClass = L"directX11_example";
	MSG msg = {};
	WNDCLASSEX wc;

	wc = { sizeof(WNDCLASSEX), CS_VREDRAW | CS_HREDRAW, wndProc, 0, 0, hInstance, (HICON)NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, windowClass, NULL };
	RegisterClassEx(&wc);

	hwnd = CreateWindow(wc.lpszClassName, L"DirectX 11 Example", WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_MAXIMIZE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, wc.hInstance, NULL);

	// initialize DirectX
	{
		DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
		swapChainDesc.Windowed = TRUE;
		swapChainDesc.OutputWindow = hwnd;
		swapChainDesc.BufferCount = 2;
		swapChainDesc.BufferDesc.Width = 0;
		swapChainDesc.BufferDesc.Height = 0;
		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.SampleDesc.Count = 1;
		swapChainDesc.SampleDesc.Quality = 0;
		swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
		swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

		D3D_FEATURE_LEVEL featureLevel;
		const D3D_FEATURE_LEVEL featureLevelArray[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_1, };
		D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_DEBUG, featureLevelArray, 3, D3D11_SDK_VERSION, &swapChainDesc, &swapChain, &device, &featureLevel, &deviceContext);

		ID3D11Texture2D* pBackBuffer;
		swapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
		device->CreateRenderTargetView(pBackBuffer, NULL, &renderTargetView);
		pBackBuffer->Release();

		RECT rc;
		GetWindowRect(hwnd, &rc);

		D3D11_VIEWPORT viewport;
		viewport.MinDepth = 0;
		viewport.MaxDepth = 1;
		viewport.TopLeftX = 0;
		viewport.TopLeftY = 0;
		viewport.Width = rc.right - rc.left;
		viewport.Height = rc.bottom - rc.top;
		deviceContext->RSSetViewports(1u, &viewport);
	}

	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);

	// draw the initial gray window
	deviceContext->ClearRenderTargetView(renderTargetView, color);
	swapChain->Present(1, 0);

	SetTimer(hwnd, 0, 500, NULL); // 500ms

	srand(GetTickCount());

	// message loop
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	KillTimer(hwnd, 0);

	// release resources
	renderTargetView->Release();
	renderTargetView = nullptr;
	swapChain->Release();
	swapChain = nullptr;
	deviceContext->Release();
	deviceContext = nullptr;
	device->Release();
	device = nullptr;

	DestroyWindow(hwnd);
	UnregisterClass(windowClass, hInstance);

	return msg.wParam;
}

Cookies are simple text files stored on the user's computer. They are used for adding features and security to this site.
OK