C++ / DirectX 11로 직접 만들기
개념 가이드에서 "무엇이 어떻게 동작하는가"를 봤다면, 여기서는 "그것을 실제로 어떻게 코딩하는가"를 다룹니다. 모든 코드는 복사해 바로 컴파일할 수 있는 수준의 Direct3D 11 예제이며, 셰이더는 HLSL(Shader Model 5.0)로 작성합니다.
이 가이드가 가정하는 것
- C++ 기본 문법 (클래스, 포인터, 표준 라이브러리)
- 개념 가이드의 내용(벡터·행렬·파이프라인·셰이더 등)을 한 번 훑어봤을 것
- Windows 10/11 + Visual Studio 2022 (Direct3D 11 SDK는 Windows SDK에 기본 포함)
개발 환경 (한 번만 세팅)
D3D11은 Windows SDK에 기본 포함이라 별도 설치가 없습니다. 링크할 라이브러리만 지정하면 됩니다.
| 구성요소 | 역할 | 비고 |
|---|---|---|
| Win32 API | 창 생성 · 입력 · 메시지 루프 | OS 기본 (GLFW 대체) |
| d3d11.lib | 디바이스 · 컨텍스트 · 리소스 | Windows SDK 포함 |
| dxgi.lib | 스왑체인 · 어댑터 열거 | Windows SDK 포함 |
| d3dcompiler.lib | 런타임 HLSL 컴파일 | Windows SDK 포함 |
| DirectXMath | 벡터/행렬 수학 (헤더 온리) | <DirectXMath.h>, GLM 대체 |
| stb_image | 이미지 로딩 (헤더 온리) | 또는 WIC |
프로젝트 설정 (Visual Studio 또는 CMake)
Visual Studio에서 빈 C++ 프로젝트를 만들고 링커 입력에 아래 라이브러리를 추가하거나, CMake라면 다음과 같습니다.
cmake_minimum_required(VERSION 3.16)
project(gfx_impl)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(app WIN32 src/main.cpp) # WIN32: 콘솔 없는 GUI 앱
# Windows SDK에 이미 포함된 라이브러리를 링크만 한다
target_link_libraries(app PRIVATE d3d11 dxgi d3dcompiler)
소스 파일 상단에서 #pragma comment로 링크해도 됩니다(Visual Studio 전용, CMake 불필요):
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3dcompiler.lib")
Release() 대신 Microsoft::WRL::ComPtr(<wrl/client.h>)를 쓰면
스마트 포인터처럼 자동 해제됩니다. 이 가이드의 예제도 ComPtr을 기본으로 씁니다.
최소 실행 코드: 창 띄우고 지우기
모든 예제의 출발점입니다. Win32로 창을 만들고, 디바이스·스왑체인을 생성한 뒤, 렌더 루프를 돕니다.
#include <windows.h>
#include <d3d11.h>
#include <dxgi.h>
#include <wrl/client.h>
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
using Microsoft::WRL::ComPtr;
ComPtr<ID3D11Device> g_device;
ComPtr<ID3D11DeviceContext> g_context;
ComPtr<IDXGISwapChain> g_swapChain;
ComPtr<ID3D11RenderTargetView> g_rtv;
// 윈도우 메시지 처리
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
if (msg == WM_DESTROY) { PostQuitMessage(0); return 0; }
return DefWindowProc(hwnd, msg, wp, lp);
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int) {
// 1) 윈도우 클래스 등록 + 창 생성
WNDCLASS wc = {};
wc.lpfnWndProc = WndProc;
wc.hInstance = hInst;
wc.lpszClassName = L"D3D11Window";
RegisterClass(&wc);
HWND hwnd = CreateWindow(wc.lpszClassName, L"DirectX 11",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1280, 720,
nullptr, nullptr, hInst, nullptr);
ShowWindow(hwnd, SW_SHOW);
// 2) 디바이스 + 스왑체인 생성 (한 번에)
DXGI_SWAP_CHAIN_DESC scd = {};
scd.BufferCount = 2;
scd.BufferDesc.Width = 1280;
scd.BufferDesc.Height = 720;
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scd.OutputWindow = hwnd;
scd.SampleDesc.Count = 1; // MSAA 없음
scd.Windowed = TRUE;
scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
D3D11CreateDeviceAndSwapChain(
nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0,
nullptr, 0, D3D11_SDK_VERSION,
&scd, &g_swapChain, &g_device, nullptr, &g_context);
// 3) 백버퍼를 렌더 타깃 뷰로 감싼다 (OpenGL의 기본 프레임버퍼에 해당)
ComPtr<ID3D11Texture2D> backBuffer;
g_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer));
g_device->CreateRenderTargetView(backBuffer.Get(), nullptr, &g_rtv);
// 4) 뷰포트 설정 (glViewport 대응)
D3D11_VIEWPORT vp = { 0, 0, 1280, 720, 0.0f, 1.0f };
g_context->RSSetViewports(1, &vp);
// 5) 렌더 루프
MSG msg = {};
while (msg.message != WM_QUIT) {
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
continue;
}
// 화면 지우기 (glClearColor + glClear 대응)
float clear[4] = { 0.06f, 0.07f, 0.10f, 1.0f };
g_context->OMSetRenderTargets(1, g_rtv.GetAddressOf(), nullptr);
g_context->ClearRenderTargetView(g_rtv.Get(), clear);
// ── 여기서 그린다 ──
g_swapChain->Present(1, 0); // V-Sync ON (glfwSwapBuffers 대응)
}
return 0;
}
OMSetRenderTargets는 매 프레임 또는 렌더 타깃이 바뀔 때마다 다시 호출해야 합니다.
또한 창 크기가 바뀌면 g_rtv를 해제하고 swapChain->ResizeBuffers() 후 RTV를 다시 만들어야 합니다.
OpenGL과 달리 백버퍼 크기가 자동으로 따라오지 않습니다.
...LH 계열 함수(XMMatrixPerspectiveFovLH 등)를 쓰면 자연스럽게 맞습니다.
각 챕터에서 해당 지점마다 짚습니다.
구현 챕터
개념 가이드와 같은 순서입니다. 각 챕터는 독립적으로 읽을 수 있지만, 1~3장이 나머지의 토대입니다.
기초 수학
벡터·행렬·변환을 C++로 한 줄 한 줄 직접 구현하고 DirectXMath로 넘어가기. 6개 세부 페이지로 분해.
2D 그래픽스
프레임버퍼에 직접 픽셀을 찍어 선·삼각형을 래스터화하기.
3D 그래픽스
버텍스 버퍼·입력 레이아웃부터 MVP·카메라·Z버퍼·퐁 조명·텍스처까지 실제 D3D11로.
GPU · 셰이더
HLSL 컴파일, 버텍스/픽셀/컴퓨트 셰이더와 상수 버퍼 작성.
그래픽스 API
D3D11 디바이스·상태 관리·렌더 루프의 실전, 그리고 타 API로의 개념 이식.
고급 렌더링
PBR·HDR·섀도우맵·디퍼드·SSAO, 그리고 CPU 레이/패스 트레이서.
실전 렌더링 기법
안티앨리어싱·감마·밉맵·투명·AO·LOD/컬링의 실전 구현.
잔디 렌더링
앞 장의 기법들이 실제로 합쳐지는 캡스톤. 대량 잔디 10가지 렌더링 기법을 D3D11/HLSL로.