# BgfxRenderer Module Module de rendu 2D pour GroveEngine, basé sur [bgfx](https://github.com/bkaradzic/bgfx). ## Features - **Abstraction RHI** : Aucune dépendance bgfx exposée hors de `BgfxDevice.cpp` - **Multi-backend** : DirectX 11/12, OpenGL, Vulkan, Metal (auto-détecté) - **MT-ready** : Architecture task-based, lock-free frame allocator - **Hot-reload** : Support complet du hot-reload GroveEngine - **Batching** : Sprites groupés par texture pour performance ## Architecture ``` BgfxRenderer/ ├── BgfxRendererModule.h/.cpp # Point d'entrée IModule ├── RHI/ # Render Hardware Interface │ ├── RHITypes.h # Handles typés, enums │ ├── RHIDevice.h # Interface abstraite │ ├── RHICommandBuffer.h/.cpp # Command recording │ └── BgfxDevice.cpp # Implémentation bgfx ├── Frame/ │ ├── FrameAllocator.h/.cpp # Allocateur lock-free │ └── FramePacket.h # Données immuables par frame ├── RenderGraph/ │ ├── RenderPass.h # Interface pass │ └── RenderGraph.h/.cpp # Gestion des passes ├── Passes/ │ ├── ClearPass.h/.cpp # Clear framebuffer │ ├── SpritePass.h/.cpp # Sprites + batching │ └── DebugPass.h/.cpp # Debug lines/shapes ├── Scene/ │ └── SceneCollector.h/.cpp # Collecte depuis IIO └── Resources/ └── ResourceCache.h/.cpp # Cache textures/shaders ``` ## Build ### Windows (recommandé pour le rendu) ```powershell cd "E:\Users\Alexis Trouvé\Documents\Projets\GroveEngine" # Build rapide .\build_renderer.bat # Ou avec options .\build_renderer.bat debug # Build Debug .\build_renderer.bat clean # Clean + rebuild .\build_renderer.bat vs # Ouvrir Visual Studio ``` ### Linux/WSL ```bash cmake -B build -DGROVE_BUILD_BGFX_RENDERER=ON cmake --build build -j4 ``` Dépendances Linux : ```bash sudo apt-get install libgl1-mesa-dev libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev ``` ## Configuration Le module est configuré via `IDataNode` dans `setConfiguration()` : ```json { "windowWidth": 1280, "windowHeight": 720, "backend": "auto", "shaderPath": "./shaders", "vsync": true, "maxSpritesPerBatch": 10000, "frameAllocatorSizeMB": 16, "nativeWindowHandle": 0 } ``` | Paramètre | Type | Défaut | Description | |-----------|------|--------|-------------| | `windowWidth` | int | 1280 | Largeur fenêtre | | `windowHeight` | int | 720 | Hauteur fenêtre | | `backend` | string | "auto" | Backend graphique (auto, opengl, vulkan, dx11, dx12, metal) | | `shaderPath` | string | "./shaders" | Chemin des shaders compilés | | `vsync` | bool | true | Synchronisation verticale | | `maxSpritesPerBatch` | int | 10000 | Sprites max par batch | | `frameAllocatorSizeMB` | int | 16 | Taille allocateur frame (MB) | | `nativeWindowHandle` | int | 0 | Handle fenêtre native (HWND, Window, etc.) | ## Communication IIO Le renderer subscribe à `render:*` et traite les messages suivants : ### Sprites ```cpp // Topic: render:sprite auto sprite = std::make_unique("sprite"); sprite->setDouble("x", 100.0); sprite->setDouble("y", 200.0); sprite->setDouble("scaleX", 1.0); sprite->setDouble("scaleY", 1.0); sprite->setDouble("rotation", 0.0); // Radians sprite->setDouble("u0", 0.0); // UV min sprite->setDouble("v0", 0.0); sprite->setDouble("u1", 1.0); // UV max sprite->setDouble("v1", 1.0); sprite->setInt("color", 0xFFFFFFFF); // RGBA sprite->setInt("textureId", 0); sprite->setInt("layer", 0); // Z-order io->publish("render:sprite", std::move(sprite)); ``` ### Batch de sprites ```cpp // Topic: render:sprite:batch auto batch = std::make_unique("batch"); auto sprites = std::make_unique("sprites"); // Ajouter plusieurs sprites comme enfants... batch->setChild("sprites", std::move(sprites)); io->publish("render:sprite:batch", std::move(batch)); ``` ### Caméra ```cpp // Topic: render:camera auto cam = std::make_unique("camera"); cam->setDouble("x", 0.0); cam->setDouble("y", 0.0); cam->setDouble("zoom", 1.0); cam->setInt("viewportX", 0); cam->setInt("viewportY", 0); cam->setInt("viewportW", 1280); cam->setInt("viewportH", 720); io->publish("render:camera", std::move(cam)); ``` ### Clear color ```cpp // Topic: render:clear auto clear = std::make_unique("clear"); clear->setInt("color", 0x303030FF); // RGBA io->publish("render:clear", std::move(clear)); ``` ### Debug (lignes et rectangles) ```cpp // Topic: render:debug:line auto line = std::make_unique("line"); line->setDouble("x1", 0.0); line->setDouble("y1", 0.0); line->setDouble("x2", 100.0); line->setDouble("y2", 100.0); line->setInt("color", 0xFF0000FF); // Rouge io->publish("render:debug:line", std::move(line)); // Topic: render:debug:rect auto rect = std::make_unique("rect"); rect->setDouble("x", 50.0); rect->setDouble("y", 50.0); rect->setDouble("w", 100.0); rect->setDouble("h", 100.0); rect->setInt("color", 0x00FF00FF); // Vert rect->setBool("filled", false); io->publish("render:debug:rect", std::move(rect)); ``` ### Topics complets | Topic | Description | |-------|-------------| | `render:sprite` | Un sprite | | `render:sprite:batch` | Batch de sprites | | `render:tilemap` | Chunk de tilemap | | `render:text` | Texte à afficher | | `render:particle` | Particule | | `render:camera` | Configuration caméra | | `render:clear` | Clear color | | `render:debug:line` | Ligne de debug | | `render:debug:rect` | Rectangle de debug | ## Intégration ### Exemple minimal ```cpp #include #include #include int main() { // Créer le gestionnaire IO auto ioManager = std::make_unique(); auto io = ioManager->createIO("renderer"); // Charger le module ModuleLoader loader; loader.load("./modules/libBgfxRenderer.dll", "renderer"); // Configurer JsonDataNode config("config"); config.setInt("windowWidth", 1920); config.setInt("windowHeight", 1080); config.setInt("nativeWindowHandle", (int)(intptr_t)hwnd); // Ton HWND auto* module = loader.getModule(); module->setConfiguration(config, io.get(), nullptr); // Main loop JsonDataNode input("input"); while (running) { input.setDouble("deltaTime", deltaTime); // Envoyer des sprites via IIO auto sprite = std::make_unique("sprite"); sprite->setDouble("x", playerX); sprite->setDouble("y", playerY); sprite->setInt("textureId", 0); io->publish("render:sprite", std::move(sprite)); // Process (collecte IIO + rendu) module->process(input); } module->shutdown(); return 0; } ``` ## Règles d'architecture | Règle | Raison | |-------|--------| | **Zéro `bgfx::` hors de `BgfxDevice.cpp`** | Abstraction propre, changement backend possible | | **FramePacket const dans les passes** | Thread-safety, pas de mutation pendant render | | **CommandBuffer par thread** | Pas de lock pendant l'encoding | | **Handles, jamais de pointeurs raw** | Indirection = safe pour relocation | | **Allocation via FrameAllocator** | Lock-free, reset gratuit chaque frame | ## TODO - [ ] Chargement textures (stb_image) - [ ] Compilation shaders (shaderc ou pré-compilés) - [ ] TilemapPass - [ ] TextPass + fonts (stb_truetype) - [ ] ParticlePass - [ ] Resize handling (window:resize) - [ ] Multi-view support - [ ] Render targets / post-process ## Dépendances - **bgfx** : Téléchargé automatiquement via CMake FetchContent - **GroveEngine::impl** : Core engine (IModule, IIO, IDataNode) - **spdlog** : Logging