- Add complete BgfxRenderer module structure (24 files) - RHI abstraction layer (no bgfx:: exposed outside BgfxDevice.cpp) - Frame system with lock-free allocator - RenderGraph with ClearPass, SpritePass, DebugPass - SceneCollector for IIO message parsing (render:* topics) - ResourceCache with thread-safe texture/shader caching - Full IModule integration (config via IDataNode, comm via IIO) - CMake with FetchContent for bgfx - Windows build script (build_renderer.bat) - Documentation (README.md, USER_GUIDE.md, PLAN_BGFX_RENDERER.md) - Updated .gitignore for Windows builds 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
265 lines
8.0 KiB
Markdown
265 lines
8.0 KiB
Markdown
# 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<JsonDataNode>("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<JsonDataNode>("batch");
|
|
auto sprites = std::make_unique<JsonDataNode>("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<JsonDataNode>("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<JsonDataNode>("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<JsonDataNode>("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<JsonDataNode>("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 <grove/ModuleLoader.h>
|
|
#include <grove/JsonDataNode.h>
|
|
#include <grove/IntraIOManager.h>
|
|
|
|
int main() {
|
|
// Créer le gestionnaire IO
|
|
auto ioManager = std::make_unique<IntraIOManager>();
|
|
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<JsonDataNode>("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
|