En aquesta secció, aprendrem a crear la nostra primera aplicació utilitzant DirectX. Aquest procés inclou la configuració inicial, la creació d'una finestra bàsica i la inicialització de Direct3D. Segueix els passos següents per començar.
- Configuració Inicial
Requisits Previs
Abans de començar, assegura't de tenir instal·lats els següents components:
- Visual Studio (preferiblement la versió més recent)
- DirectX SDK (si no està inclòs en el teu Visual Studio)
Crear un Nou Projecte
- Obre Visual Studio.
- Selecciona File > New > Project.
- Tria Windows Desktop Application i assegura't que el tipus de projecte sigui Empty Project.
- Assigna un nom al teu projecte i selecciona la ubicació on vols guardar-lo.
- Crear una Finestra Bàsica
Incloure les Llibreries Necessàries
Afegeix les següents llibreries al teu projecte per utilitzar les funcions de Windows i DirectX:
Definir la Funció WinMain
La funció WinMain és el punt d'entrada de les aplicacions Windows. Aquí és on inicialitzarem la finestra.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pScmdline, int iCmdshow) {
// Definir i registrar la classe de finestra
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = "WindowClass";
RegisterClassEx(&wc);
// Crear la finestra
HWND hwnd = CreateWindowEx(NULL, "WindowClass", "DirectX Application", WS_OVERLAPPEDWINDOW, 300, 300, 800, 600, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdshow);
// Bucle de missatges
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}Definir la Funció WindowProc
La funció WindowProc gestiona els missatges de la finestra.
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
- Inicialitzar Direct3D
Crear Dispositiu i Context de Dispositiu
Afegeix el següent codi per inicialitzar Direct3D:
IDXGISwapChain *swapchain; // la cadena d'intercanvi
ID3D11Device *dev; // el dispositiu
ID3D11DeviceContext *devcon; // el context del dispositiu
void InitD3D(HWND hwnd) {
// Descripció de la cadena d'intercanvi
DXGI_SWAP_CHAIN_DESC scd;
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
scd.BufferCount = 1;
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scd.OutputWindow = hwnd;
scd.SampleDesc.Count = 4;
scd.Windowed = TRUE;
scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
// Crear el dispositiu, el context del dispositiu i la cadena d'intercanvi
D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL, D3D11_SDK_VERSION, &scd, &swapchain, &dev, NULL, &devcon);
}Configurar el Render Target
Afegeix el següent codi per configurar el render target:
ID3D11RenderTargetView *backbuffer;
void CreateRenderTarget() {
// Obtenir el buffer de la cadena d'intercanvi
ID3D11Texture2D *pBackBuffer;
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
// Crear el render target view
dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
pBackBuffer->Release();
// Configurar el render target
devcon->OMSetRenderTargets(1, &backbuffer, NULL);
}Configurar el Viewport
Afegeix el següent codi per configurar el viewport:
void SetViewport() {
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = 800;
viewport.Height = 600;
devcon->RSSetViewports(1, &viewport);
}Integrar la Inicialització a WinMain
Actualitza la funció WinMain per incloure la inicialització de Direct3D:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pScmdline, int iCmdshow) {
// Definir i registrar la classe de finestra
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = "WindowClass";
RegisterClassEx(&wc);
// Crear la finestra
HWND hwnd = CreateWindowEx(NULL, "WindowClass", "DirectX Application", WS_OVERLAPPEDWINDOW, 300, 300, 800, 600, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdshow);
// Inicialitzar Direct3D
InitD3D(hwnd);
CreateRenderTarget();
SetViewport();
// Bucle de missatges
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Alliberar recursos
swapchain->Release();
backbuffer->Release();
dev->Release();
devcon->Release();
return msg.wParam;
}
- Renderitzar un Color de Fons
Afegir la Funció de Renderització
Afegeix la següent funció per renderitzar un color de fons:
void RenderFrame() {
// Especificar el color de fons
float color[4] = {0.0f, 0.2f, 0.4f, 1.0f};
devcon->ClearRenderTargetView(backbuffer, color);
// Intercanviar els buffers
swapchain->Present(0, 0);
}Integrar la Funció de Renderització al Bucle de Missatges
Actualitza el bucle de missatges per cridar la funció RenderFrame:
MSG msg;
while (TRUE) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
RenderFrame();
}
}Conclusió
En aquesta secció, hem creat la nostra primera aplicació DirectX. Hem configurat una finestra bàsica, inicialitzat Direct3D, configurat el render target i el viewport, i hem renderitzat un color de fons. Aquest és el primer pas per començar a treballar amb DirectX. En les següents seccions, aprofundirem en conceptes més avançats i començarem a renderitzar objectes 3D.
Exercici Pràctic:
- Modifica el color de fons a un altre color de la teva elecció.
- Afegeix un comptador de fotogrames per segon (FPS) a la finestra.
Solució de l'Exercici:
// Modificar el color de fons
float color[4] = {0.0f, 0.5f, 0.0f, 1.0f}; // Color verd
// Comptador de FPS
#include <chrono>
auto start = std::chrono::high_resolution_clock::now();
int frameCount = 0;
while (TRUE) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
RenderFrame();
frameCount++;
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<float> duration = end - start;
if (duration.count() >= 1.0f) {
char title[256];
sprintf_s(title, "DirectX Application - FPS: %d", frameCount);
SetWindowText(hwnd, title);
frameCount = 0;
start = std::chrono::high_resolution_clock::now();
}
}
}Amb aquests canvis, hauràs personalitzat el color de fons i afegit un comptador de FPS a la teva aplicació.
Curs de Programació DirectX
Mòdul 1: Introducció a DirectX
- Què és DirectX?
- Configuració de l'Entorn de Desenvolupament
- Comprendre l'API de DirectX
- Crear la Teva Primera Aplicació DirectX
Mòdul 2: Conceptes Bàsics de Direct3D
- Introducció a Direct3D
- Inicialitzar Direct3D
- Renderitzar un Triangle
- Gestionar el Bucle de Renderització
Mòdul 3: Treballar amb Shaders
Mòdul 4: Tècniques Avançades de Renderització
Mòdul 5: Models 3D i Animació
Mòdul 6: Optimització del Rendiment
- Perfilat i Depuració
- Optimitzar el Rendiment de la Renderització
- Gestió de Memòria
- Multifil en DirectX
