Like On Facebook

header ads

Estrutura básica de um aplicativo DirectX


Para estruturar um aplicativo básico em DirectX, vamos desenvolver uma organização simples e modular que cubra as funções essenciais para a inicialização e renderização. Essa estrutura permitirá que você gerencie a janela, configure o DirectX, e renderize uma tela básica. Vou dividir isso em módulos principais para deixar mais claro.

Estrutura Básica de um Aplicativo DirectX

  1. Módulo Principal (main.cpp): onde fica a entrada do aplicativo (WinMain) e o loop principal de execução.
  2. Classe DirectXApp: uma classe que encapsula toda a lógica de inicialização e renderização do DirectX.
  3. Função de Processamento de Mensagens (WindowProc): responsável por gerenciar as mensagens do Windows.

Aqui está um esboço de como organizar cada uma dessas partes:


1. Módulo Principal (main.cpp)

Este módulo contém a função de entrada WinMain, que cria uma instância da nossa classe de aplicativo DirectX (DirectXApp), executa o loop de mensagens e chama a função de renderização.

 #include <windows.h>
 #include "DirectXApp.h"  // Inclui a classe que vamos criar

 // Função de entrada do Windows
 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) {
     // Inicializa a aplicação DirectX
     DirectXApp dxApp;
     if (!dxApp.Initialize(hInstance, nCmdShow)) {
         MessageBox(nullptr, "Falha ao inicializar o DirectX.", "Erro", MB_OK | MB_ICONERROR);
         return -1;
     }

     // Loop principal de mensagens
     MSG msg = {};
     while (msg.message != WM_QUIT) {
         if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
             TranslateMessage(&msg);
             DispatchMessage(&msg);
         } else {
             dxApp.Render();  // Renderiza a cada loop
         }
     }

     return static_cast(msg.wParam);
 }

Explicação 

  • WinMain: Inicializa uma instância de DirectXApp. Se a inicialização falha, exibe uma mensagem de erro. 

  • Loop Principal de Mensagens: Mantém o aplicativo em execução enquanto espera mensagens do sistema operacional (eventos de usuário, notificações do sistema etc.). No caso de não haver mensagens (PeekMessage retorna falso), a função Render é chamada para atualizar a tela.

2. Classe DirectXApp 

A classe DirectXApp encapsula a lógica de inicialização e renderização do DirectX. Esta estrutura modulariza o código e facilita o gerenciamento dos recursos gráficos.

DirectXApp.h
 #pragma once
 #include <d3d11.h>
 #include <windows.h>

 class DirectXApp {
 public:
     DirectXApp() : g_device(nullptr), g_context(nullptr), g_renderTargetView(nullptr), hwnd(nullptr) {}
     ~DirectXApp();

     bool Initialize(HINSTANCE hInstance, int nCmdShow);
     void Render();

 private:
     HWND hwnd;                           // Handle da janela
     ID3D11Device* g_device;              // Dispositivo Direct3D
     ID3D11DeviceContext* g_context;      // Contexto do dispositivo
     IDXGISwapChain* g_swapChain;         // Troca de buffers
     ID3D11RenderTargetView* g_renderTargetView; // Visão de destino de renderização

     bool InitializeWindow(HINSTANCE hInstance, int nCmdShow);
     bool InitializeDirectX();
 };

DirectXApp.cpp
 #include "DirectXApp.h"
 #include <stdexcept>

 // Inicializa o DirectX e a janela
 bool DirectXApp::Initialize(HINSTANCE hInstance, int nCmdShow) {
     if (!InitializeWindow(hInstance, nCmdShow))
         return false;
     if (!InitializeDirectX())
         return false;
     return true;
 }

 bool DirectXApp::InitializeWindow(HINSTANCE hInstance, int nCmdShow) {
     const char CLASS_NAME[] = "DirectX Window Class";

     WNDCLASS wc = {};
     wc.lpfnWndProc = WindowProc;
     wc.hInstance = hInstance;
     wc.lpszClassName = CLASS_NAME;

     RegisterClass(&wc);

     hwnd = CreateWindowEx(
         0, CLASS_NAME, "Meu Aplicativo DirectX",
         WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
         nullptr, nullptr, hInstance, nullptr);

     if (!hwnd) return false;

     ShowWindow(hwnd, nCmdShow);
     return true;
 }

 bool DirectXApp::InitializeDirectX() {
     DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
     swapChainDesc.BufferCount = 1;
     swapChainDesc.BufferDesc.Width = 800;
     swapChainDesc.BufferDesc.Height = 600;
     swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
     swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
     swapChainDesc.OutputWindow = hwnd;
     swapChainDesc.SampleDesc.Count = 1;
     swapChainDesc.Windowed = TRUE;

     HRESULT hr = D3D11CreateDeviceAndSwapChain(
         nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0,
         D3D11_SDK_VERSION, &swapChainDesc, &g_swapChain, &g_device,
         nullptr, &g_context);

     if (FAILED(hr)) return false;

     ID3D11Texture2D* backBuffer = nullptr;
     hr = g_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer));
     if (FAILED(hr)) return false;

     hr = g_device->CreateRenderTargetView(backBuffer, nullptr, &g_renderTargetView);
     backBuffer->Release();
     if (FAILED(hr)) return false;

     g_context->OMSetRenderTargets(1, &g_renderTargetView, nullptr);

     D3D11_VIEWPORT viewport = {};
     viewport.Width = 800;
     viewport.Height = 600;
     viewport.TopLeftX = 0;
     viewport.TopLeftY = 0;
     g_context->RSSetViewports(1, &viewport);

     return true;
 }

 void DirectXApp::Render() {
     float clearColor[4] = { 0.0f, 0.2f, 0.4f, 1.0f };
     g_context->ClearRenderTargetView(g_renderTargetView, clearColor);

     g_swapChain->Present(1, 0);
 }

 DirectXApp::~DirectXApp() {
     if (g_renderTargetView) g_renderTargetView->Release();
     if (g_swapChain) g_swapChain->Release();
     if (g_context) g_context->Release();
     if (g_device) g_device->Release();
 }

Explicação 

  • Initialize: Chama as funções InitializeWindow e InitializeDirectX para configurar a janela e o DirectX.

  • InitializeWindow: Configura e cria a janela. 

  • InitializeDirectX: Cria o dispositivo, contexto, e a troca de buffers. Configura a visão de destino e a viewport para renderização. 

  • Render: Limpa a tela com uma cor de fundo azul e apresenta o conteúdo da renderização na tela. 

  • Destrutor: Libera todos os recursos alocados pelo DirectX.


3. Função de Processamento de Mensagens (WindowProc

A função WindowProc processa as mensagens enviadas pelo sistema operacional para a janela.
 #include <windows.h>

 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);
     }
 }

Explicação 

  • WM_DESTROY: Quando a janela é fechada, esta mensagem é enviada e o PostQuitMessage(0) encerra o loop de mensagens. 

  • DefWindowProc: Processa todas as mensagens que não foram capturadas especificamente.

Resumo e Funcionamento 
  1. Inicialização: WinMain cria uma instância de DirectXApp e inicializa a janela e o DirectX. 
  2. Loop de Mensagens e Renderização: O loop verifica se há mensagens e, caso não haja, chama a função Render.
  3. Limpeza de Recursos: Quando o aplicativo é encerrado, o destrutor da DirectXApp libera todos os recursos DirectX. 

Essa estrutura básica é extensível. Com ela, você pode adicionar lógica de renderização, manipulação de entradas e mais componentes DirectX para avançar seu desenvolvimento.

Postar um comentário

1 Comentários