En esta sección, aprenderás a crear tu primera aplicación DirectX desde cero. Este proceso te ayudará a familiarizarte con los conceptos básicos y la estructura de una aplicación DirectX. Asegúrate de haber configurado tu entorno de desarrollo correctamente antes de comenzar.

Objetivos

  • Configurar una ventana de aplicación básica.
  • Inicializar DirectX.
  • Renderizar un color de fondo simple.

Paso 1: Configuración de la Ventana de Aplicación

Primero, necesitamos crear una ventana de aplicación básica en Windows. Aquí está el código para configurar una ventana simple:

#include <windows.h>

// Prototipos de funciones
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

// Punto de entrada de la aplicación
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    // Estructura de la ventana
    WNDCLASSEX wc = {0};
    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 + 1);
    wc.lpszClassName = "WindowClass";

    // Registro de la ventana
    RegisterClassEx(&wc);

    // Creación de la ventana
    HWND hwnd = CreateWindowEx(0, "WindowClass", "DirectX Application", WS_OVERLAPPEDWINDOW, 100, 100, 800, 600, NULL, NULL, hInstance, NULL);

    // Mostrar la ventana
    ShowWindow(hwnd, nCmdShow);

    // Bucle de mensajes
    MSG msg = {0};
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

// Procedimiento de la ventana
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
}

Explicación del Código

  • WinMain: Punto de entrada de la aplicación. Configura y muestra la ventana.
  • WNDCLASSEX: Estructura que define la clase de ventana.
  • RegisterClassEx: Registra la clase de ventana.
  • CreateWindowEx: Crea la ventana.
  • ShowWindow: Muestra la ventana.
  • GetMessage, TranslateMessage, DispatchMessage: Bucle de mensajes que mantiene la aplicación en ejecución.
  • WindowProc: Procedimiento de la ventana que maneja los mensajes de la ventana.

Paso 2: Inicialización de DirectX

Ahora que tenemos una ventana, necesitamos inicializar DirectX. Utilizaremos Direct3D 11 para este propósito.

Código de Inicialización de Direct3D

#include <d3d11.h>
#pragma comment (lib, "d3d11.lib")

IDXGISwapChain* swapChain;
ID3D11Device* dev;
ID3D11DeviceContext* devcon;
ID3D11RenderTargetView* backBuffer;

void InitD3D(HWND hwnd) {
    // Estructura de la cadena de intercambio
    DXGI_SWAP_CHAIN_DESC scd = {0};
    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;

    // Creación del dispositivo, contexto y cadena de intercambio
    D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &scd, &swapChain, &dev, NULL, &devcon);

    // Obtener el buffer de la cadena de intercambio
    ID3D11Texture2D* pBackBuffer;
    swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);

    // Crear la vista de destino de renderizado
    dev->CreateRenderTargetView(pBackBuffer, NULL, &backBuffer);
    pBackBuffer->Release();

    // Configurar el contexto de dispositivo
    devcon->OMSetRenderTargets(1, &backBuffer, NULL);
}

void CleanD3D() {
    swapChain->Release();
    backBuffer->Release();
    dev->Release();
    devcon->Release();
}

Explicación del Código

  • DXGI_SWAP_CHAIN_DESC: Describe la cadena de intercambio.
  • D3D11CreateDeviceAndSwapChain: Crea el dispositivo Direct3D, el contexto y la cadena de intercambio.
  • ID3D11Texture2D: Representa el buffer de la cadena de intercambio.
  • CreateRenderTargetView: Crea la vista de destino de renderizado.
  • OMSetRenderTargets: Configura el contexto de dispositivo para usar la vista de destino de renderizado.

Paso 3: Renderizando un Color de Fondo

Finalmente, renderizaremos un color de fondo simple.

Código de Renderizado

void RenderFrame() {
    // Color de fondo (RGBA)
    float color[4] = {0.0f, 0.2f, 0.4f, 1.0f};

    // Limpiar el buffer de fondo
    devcon->ClearRenderTargetView(backBuffer, color);

    // Presentar el buffer
    swapChain->Present(0, 0);
}

Integración en el Bucle de Mensajes

Modifica el bucle de mensajes para incluir la inicialización y el renderizado de Direct3D:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    // ... (código de configuración de la ventana)

    // Inicializar Direct3D
    InitD3D(hwnd);

    // Bucle de mensajes
    MSG msg = {0};
    while (TRUE) {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
            if (msg.message == WM_QUIT) break;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        } else {
            // Renderizar el frame
            RenderFrame();
        }
    }

    // Limpiar Direct3D
    CleanD3D();

    return msg.wParam;
}

Resumen

En esta sección, has aprendido a:

  • Configurar una ventana de aplicación básica en Windows.
  • Inicializar Direct3D.
  • Renderizar un color de fondo simple.

Estos pasos son fundamentales para cualquier aplicación DirectX. En los próximos módulos, profundizaremos en conceptos más avanzados y técnicas de renderizado. ¡Felicidades por crear tu primera aplicación DirectX!

© Copyright 2024. Todos los derechos reservados