Compare commits

...

6 Commits

Author SHA1 Message Date
Jérôme Bousquié e8e9124a9d doc : single buffer 2026-08-03 21:52:36 +02:00
Jérôme Bousquié 895965750f préparation phase 1.1 2026-08-01 21:25:43 +02:00
Jérôme Bousquié 37432536dc refactor spec OKF 2026-08-01 09:34:12 +02:00
Jérôme Bousquié 81b825970a correction contradictions 2026-07-31 20:43:57 +02:00
Jérôme Bousquié 8d61e4231e spec OKF pour doc 2026-07-31 19:10:04 +02:00
Jérôme Bousquié 2cc79be2ec spec OKF pour doc 2026-07-31 19:09:46 +02:00
38 changed files with 2113 additions and 115 deletions
View File
View File
+7
View File
@@ -43,3 +43,10 @@ WGPU doesn't have a native "Context" object — this type groups them together f
- wgpu 30.0.0 is pinned in `lib/Cargo.toml`. The comment says "check the latest version" — verify compatibility before upgrading. - wgpu 30.0.0 is pinned in `lib/Cargo.toml`. The comment says "check the latest version" — verify compatibility before upgrading.
- No feature flags, no dev-dependencies, no tests yet. Adding any requires updating both `Cargo.toml` files if the dependency spans crates. - No feature flags, no dev-dependencies, no tests yet. Adding any requires updating both `Cargo.toml` files if the dependency spans crates.
- The workspace has no `[workspace.dependencies]` section. Dependencies are declared per-crate rather than centrally. - The workspace has no `[workspace.dependencies]` section. Dependencies are declared per-crate rather than centrally.
<!-- lean-ctx -->
## lean-ctx
Prefer lean-ctx MCP tools over native equivalents for token savings.
Full rules: @LEAN-CTX.md
<!-- /lean-ctx -->
+45
View File
@@ -0,0 +1,45 @@
# WSG - WGPU Simple Graphics Library
## Project Type
Rust workspace (2024 edition) wrapping [wgpu](https://github.com/gfx-rs/wgpu) for simple 3D drawing operations.
## Workspace Structure
```
Cargo.toml # workspace root — no dependencies here
lib/Cargo.toml # wsg-lib crate: wgpu 30.0.0, winit 0.30
examples/Cargo.toml # depends on wsg-lib via path reference
lib/lib.rs # lib entry point
lib/context.rs # Context type (aggregates wgpu objects: Instance, Surface, Adapter, Device, Queue)
lib/renderer.rs # renderer implementation
examples/src/main.rs # example binary
```
**Key convention**: `wsg-lib` is referenced from `examples/` via relative path (`path = "../lib"`). Do not publish this to crates.io as-is — it uses a local path dependency.
## Essential Commands
| Action | Command |
|--------|---------|
| Build everything | `cargo build --workspace` |
| Run examples | `cargo run -p examples` |
| Test | `cargo test --workspace` |
| Check | `cargo check --workspace` |
| Format | `cargo fmt --all` |
No custom scripts or linting tooling beyond standard Cargo conventions.
## Architecture Overview
The library's purpose is to abstract the five core wgpu objects into a single **Context**:
- **Instance** — GPU backend selection (Vulkan/Metal/DX12)
- **Surface** — window rendering surface (via winit)
- **Adapter** — physical/logical GPU device
- **Device** — buffer/texture/pipeline creation
- **Queue** — command submission
WGPU doesn't have a native "Context" object — this type groups them together for a simpler user API. See README.md for the French documentation of each component.
## Gotchas
- Rust 2024 edition is used. Ensure your Rust toolchain supports it (`rustup update`).
- wgpu 30.0.0 is pinned in `lib/Cargo.toml`. The comment says "check the latest version" — verify compatibility before upgrading.
- No feature flags, no dev-dependencies, no tests yet. Adding any requires updating both `Cargo.toml` files if the dependency spans crates.
- The workspace has no `[workspace.dependencies]` section. Dependencies are declared per-crate rather than centrally.
Generated
+8
View File
@@ -501,6 +501,12 @@ dependencies = [
"xml-rs", "xml-rs",
] ]
[[package]]
name = "glam"
version = "0.33.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f22fb22f065b308be0d8724e3706c7fa3fc2a6c7d6899df4cad7860e7a75436"
[[package]] [[package]]
name = "glow" name = "glow"
version = "0.17.0" version = "0.17.0"
@@ -2323,7 +2329,9 @@ name = "wsg-lib"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
"glam",
"pollster", "pollster",
"slotmap",
"thiserror 2.0.18", "thiserror 2.0.18",
"wgpu", "wgpu",
"winit", "winit",
+50
View File
@@ -0,0 +1,50 @@
<!-- lean-ctx-owned: PROJECT-LEAN-CTX.md v1 -->
# lean-ctx — Context Engineering Layer
<!-- lean-ctx-rules-v11 -->
## Tool Mapping (MANDATORY — use instead of native equivalents)
| Instead of | Use | Example |
|------------|-----|---------|
| Read/cat/head/tail | `ctx_read(path, mode)` | `ctx_read("src/main.rs", "full")` |
| Grep/rg/find | `ctx_search(pattern, path)` | `ctx_search("fn handle", "src/")` |
| Shell/bash | `ctx_shell(command)` | `ctx_shell("cargo test")` |
| Edit (when Read unavailable) | `ctx_edit(path, old, new)` | `ctx_edit("f.rs", "old", "new")` |
## ctx_read Mode Selection
| Goal | Mode | When |
|------|------|------|
| Edit this file | `full` | Before any edit |
| Understand API | `signatures` | Context-only, won't edit |
| Re-read after edit | `diff` | Post-edit verification |
| Large file overview | `map` | >500 lines, won't edit |
| Specific region | `lines:N-M` | Know exact location |
| Unsure | `auto` | System selects optimal mode |
## Workflow (follow this order)
1. **Orient:** `ctx_overview(task)` or `ctx_compose(task, path)` for unfamiliar tasks
2. **Locate:** `ctx_search(pattern, path)` for exact text; `ctx_semantic_search(query)` for concepts
3. **Read:** `ctx_read(path, mode)` with appropriate mode from table above
4. **Edit:** `ctx_edit(path, old_string, new_string)` or native Edit if available
5. **Verify:** `ctx_read(path, "diff")` + `ctx_shell("test command")`
6. **Record:** `ctx_knowledge(action="remember", content="...")` for non-obvious findings
## Proactive (use without being asked)
- `ctx_overview(task)` — at session start for orientation
- `ctx_compress` — when context grows large (at phase boundaries)
- `ctx_knowledge(action="wakeup")` — at session start to surface prior findings
## Compression Bypass (only when compressed output hides needed detail)
`ctx_read(path, "lines:N-M")``ctx_read(path, "full")``ctx_shell(cmd, raw=true)`
Return to compressed defaults after one expanded retrieval.
## Risk Gate (before high-impact edits)
Before editing exported symbols, auth, DB schemas, or 3+ files: run `ctx_impact(action="analyze")`
and `ctx_callgraph(action="callers")` to confirm blast radius.
## Session
- **Start:** `ctx_session(action="status")` + `ctx_knowledge(action="wakeup")`
- **End:** `ctx_session(action="decision", content="what was done + next steps")`
- **On [CHECKPOINT]:** `ctx_session(action="task", value="current status")`
NEVER use native Read/Grep/Shell when ctx_* equivalents are available.
<!-- /lean-ctx -->
+3
View File
@@ -2,6 +2,9 @@
WSG is a Rust library that wraps [wgpu](https://github.com/gfx-rs/wgpu) to provide a simple, declarative API for 3D graphics. It abstracts away the complexity of managing GPU resources while exposing low-level primitives for advanced users. WSG is a Rust library that wraps [wgpu](https://github.com/gfx-rs/wgpu) to provide a simple, declarative API for 3D graphics. It abstracts away the complexity of managing GPU resources while exposing low-level primitives for advanced users.
NOTE : the development version is currently unstable and the examples described below may not work as expected.
## What it does ## What it does
WSG provides two complementary workflows: WSG provides two complementary workflows:
-82
View File
@@ -1,82 +0,0 @@
# Architecture du Moteur wsg_lib
wsg_lib est un moteur de rendu modulaire basé sur wgpu. Il adopte une architecture à deux niveaux : une façade de haut niveau pour la productivité et un accès bas niveau pour un contrôle total.
## 1. Philosophie et Principes
- **Abstraction vs Transparence** : Le moteur masque la complexité (wgpu, winit, gestion des Frame) via `App`, tout en exposant les briques élémentaires pour les utilisateurs avancés.
- **Approche orientée Scène** : Le rendu repose sur la composition d'une `Scene` contenant les entités, matériaux et géométries.
- **Pipeline Data-Driven** : Les ressources (Shaders, Meshes, Materials) sont découplées. Le `PipelineCache` gère automatiquement la compilation et la réutilisation des pipelines GPU.
## 2. Organisation des Modules (`lib/src/`)
- **`core/`** : Plomberie système (`Context`, `Renderer`, `Frame`). Accès bas niveau.
- **`pipeline/`** : `PipelineCache` pour la gestion des états GPU et shaders.
- **`resources/`** : Données (`Mesh`, `Material`, `Vertex`).
- **`scene/`** : Hiérarchie et stockage des objets à visualiser (Entités, Transformations).
- **`shaders/`** : Assets WGSL.
- **`utils/`** : Utilitaires transverses.
## 3. Interfaces de Haut Niveau (`App` & `AppHandler`)
### L'objet `App`
La façade `App` orchestre la boucle de jeu. Elle encapsule :
- Le cycle de vie de la fenêtre.
- La boucle d'événements.
- La gestion automatique des Frame (acquisition et présentation).
### Le trait `AppHandler`
L'utilisateur implémente ce trait pour définir la logique métier :
```rust
pub trait AppHandler {
// Appelé avant la préparation de la frame
fn update(&mut self, _app: &mut App) {}
// Appelé au moment de la présentation
fn render(&mut self, app: &mut App);
}
```
## 4. Workflow et Cycle de Vie
### A. Initialisation (Configuration)
- **Shaders** : Chargés avant la renderloop.
- **PipelineCache** : Enregistre les shaders.
- **Matériaux** : Créés avec un shader associé. Un mesh sans matériau explicite utilise `basic_shader` par défaut.
- **Scene** : Assemblage des objets. L'utilisateur peuple la scène via `app.scene`.
### B. Boucle de Rendu (Automatisée)
Le moteur gère la renderloop interne :
1. **Update** : Appel à `AppHandler::update`.
2. **Acquisition** : Gestion interne de `wgpu::SurfaceTexture`.
3. **Render** : Appel à `AppHandler::render` où l'utilisateur exécute `app.render(scene)`.
4. **Présentation** : Gestion interne de `present()`.
## 5. Accès Avancé
Les utilisateurs souhaitant ignorer l'abstraction `App` peuvent accéder directement à :
- `wsg_lib::core::Context` et `Renderer` pour gérer manuellement les RenderPass.
- `wsg_lib::pipeline::PipelineCache` pour des besoins de shaders personnalisés.
- `winit` pour la gestion précise des événements système.
## 6. Structure des données (pour LLM)
```
App (Facade) -> Scene (Conteneur) -> Entities -> Mesh + Material (Shader)
|
+-> Renderer (WGPU) <-> PipelineCache (Shaders)
```
## Notes pour l'implémentation future
- `app.render(scene)` : Cette méthode doit devenir l'API principale pour le rendu de la scène complète.
- Trait `AppHandler` : Il est recommandé de faire passer la `Scene` ou une référence à celle-ci comme argument ou de permettre à `AppHandler` d'être le lieu où la `Scene` est manipulée (ex : `MyGame { scene: Scene, ... }`).
- `PipelineCache` : Son utilisation doit être invisible pour l'utilisateur standard lors de la création d'un `Material`.
+33 -24
View File
@@ -1,6 +1,15 @@
---
type: Plan
title: Implementation Plan for wsg_lib Engine Consolidation and Finalization
description: Implementation plan defining priority steps to finalize the current architecture, making the API intuitive for standard users while maintaining power for advanced users
tags: [plan, implementation, roadmap, development, wsg-lib]
status: stable
generated: { by: human:jerome, at: 2026-07-31T00:00:00Z }
---
# Plan d'Implémentation : Consolidation et Finalisation du Moteur wsg_lib # Plan d'Implémentation : Consolidation et Finalisation du Moteur wsg_lib
Ce plan définit les étapes prioritaires pour stabiliser l'architecture actuelle. L'objectif est de rendre l'API intuitive pour l'utilisateur standard tout en conservant la puissance de contrôle pour l'utilisateur avancé. Ce plan définit les étapes prioritaires pour finaliser l'architecture actuelle. L'objectif est de rendre l'API intuitive pour l'utilisateur standard tout en conservant la puissance de contrôle pour l'utilisateur avancé.
## Phase 1 : Finalisation et Nettoyage de l'Existant (Priorité Absolue) ## Phase 1 : Finalisation et Nettoyage de l'Existant (Priorité Absolue)
@@ -8,20 +17,20 @@ Cette phase vise à supprimer la dette technique et à unifier les accès.
### Uniformisation des Modules ### Uniformisation des Modules
- Vérifier que tous les traits (`AppHandler`) et structures (`App`, `Context`) sont explicitement marqués `pub` dans leurs fichiers sources. - [X] Vérifier que tous les traits (`AppHandler`) et structures (`App`, `Context`) sont explicitement marqués `pub` dans leurs fichiers sources.
- Ré-exporter l'API dans `lib.rs` pour permettre des imports simplifiés (ex : `use wsg_lib::{App, AppHandler}`). - [X] Ré-exporter l'API dans `lib.rs` pour permettre des imports simplifiés (ex : `use wsg_lib::{App, AppHandler}`).
- Nettoyer les accès internes pour que l'utilisateur n'ait pas à importer les modules système (`core`, `pipeline`) sauf besoin spécifique. - [X] Nettoyer les accès internes pour que l'utilisateur n'ait pas à importer les modules système (`core`, `pipeline`) sauf besoin spécifique.
### Abstraction de la Boucle (`App::run`) ### Abstraction de la Boucle (`App::run`)
- Déplacer la gestion de `winit::event_loop` et des `Frame` à l'intérieur de la méthode `run()` de `App`. - [X] Déplacer la gestion de `winit::event_loop` et des `Frame` à l'intérieur de la méthode `run()` de `App`.
- Garantir que le trait `AppHandler` reçoit une référence à `App` permettant d'appeler `app.renderer` ou `app.scene`. - [X] Garantir que le trait `AppHandler` reçoit une référence à `App` permettant d'appeler `app.renderer` ou `app.scene`.
- Supprimer toute gestion de `Frame` ou `EventLoop` manuelle des exemples utilisateurs (`simple.rs`). - [X] Supprimer toute gestion de `Frame` ou `EventLoop` manuelle des exemples utilisateurs (`simple.rs`).
### Correction du Builder et Initialisation ### Correction du Builder et Initialisation
- Standardiser la création de `App` via un `AppBuilder` robuste. - [X] Standardiser la création de `App` via un `AppBuilder` robuste.
- Gérer les `dev-dependencies` dans `lib/Cargo.toml` (notamment `pollster` avec la feature `macro`) pour permettre la compilation des exemples sans polluer les dépendances finales de la librairie. - [X] Gérer les `dev-dependencies` dans `lib/Cargo.toml` (notamment `pollster` avec la feature `macro`) pour permettre la compilation des exemples sans polluer les dépendances finales de la librairie.
## Phase 2 : Structure de Rendu et Scène ## Phase 2 : Structure de Rendu et Scène
@@ -29,39 +38,39 @@ Une fois la plomberie encapsulée, nous devons rendre l'assemblage des objets co
### Intégration de la Scene ### Intégration de la Scene
- Formaliser la structure `Scene` : un conteneur qui liste les Entities. - [X] Formaliser la structure `Scene` : un conteneur qui liste les Entities.
- Associer le `PipelineCache` à la Scene pour que le rendu des matériaux soit automatique. - [X] Associer le `PipelineCache` à la Scene pour que le rendu des matériaux soit automatique.
- Implémenter la logique `app.render(scene)` : cette méthode doit parcourir la scène, récupérer les matériaux, gérer les pipelines via le cache, et soumettre les draw calls. - [X] Implémenter la logique `app.render(scene)` : cette méthode doit parcourir la scène, récupérer les matériaux, gérer les pipelines via le cache, et soumettre les draw calls.
### Gestion des Matériaux et Shaders ### Gestion des Matériaux et Shaders
- S'assurer que chaque Mesh possède une référence vers un Material. - [X] S'assurer que chaque Mesh possède une référence vers un Material.
- Implémenter le comportement par défaut : si aucun matériau n'est assigné, le moteur injecte automatiquement le `basic_shader`. - [X] Implémenter le comportement par défaut : si aucun matériau n'est assigné, le moteur injecte automatiquement le `basic_shader`.
## Phase 3 : Documentation et Interface (API "User-Friendly") ## Phase 3 : Documentation et Interface (API "User-Friendly")
### Refonte des Exemples ### Refonte des Exemples
- `simple.rs` doit devenir le modèle : **15 lignes** de code, pas de manipulation WGPU explicite. - [X] `simple.rs` doit devenir le modèle : **15 lignes** de code, pas de manipulation WGPU explicite.
- `manual.rs` doit rester disponible en tant que tutoriel pour ceux qui veulent contourner l'abstraction App. - [X] `manual.rs` doit rester disponible en tant que tutoriel pour ceux qui veulent contourner l'abstraction App.
### Nettoyage du Code Interne ### Nettoyage du Code Interne
- Vérifier les durées de vie (lifetimes) et les Arc pour s'assurer qu'aucune fuite mémoire ou accès concurrentiel invalide ne survient lors des changements de frame. - [X] Vérifier les durées de vie (lifetimes) et les Arc pour s'assurer qu'aucune fuite mémoire ou accès concurrentiel invalide ne survient lors des changements de frame.
## Phase 4 : Nouvelles Fonctionnalités (Planification Future) ## Phase 4 : Nouvelles Fonctionnalités (Planification Future)
Une fois les phases 1 à 3 validées, nous pourrons introduire : Une fois les phases 1 à 3 validées, nous pourrons introduire :
- **Système de Lumières** : Ajout de buffers d'uniformes dans le PipelineCache. - [ ] **Système de Lumières** : Ajout de buffers d'uniformes dans le PipelineCache.
- **Textures** : Intégration d'un module de chargement d'images et de BindGroups. - [ ] **Textures** : Intégration d'un module de chargement d'images et de BindGroups.
- **Caméras** : Gestion des matrices de projection/vue dans la Scene. - [ ] **Caméras** : Gestion des matrices de projection/vue dans la Scene.
## Check-list de Vérification pour le LLM d'Assistance ## Check-list de Vérification pour le LLM d'Assistance
- [ ] Est-ce que `simple.rs` compile sans importer `winit` ou `wgpu` ? - [X] Est-ce que `simple.rs` compile sans importer `winit` ou `wgpu` ?
- [ ] Est-ce que `App::run` gère bien le cycle update → render → present ? - [X] Est-ce que `App::run` gère bien le cycle update → render → present ?
- [ ] Les modules sont-ils bien exposés via `lib.rs` ? - [X] Les modules sont-ils bien exposés via `lib.rs` ?
- [ ] `pollster` est-il uniquement en dev-dependencies ? - [X] `pollster` est-il uniquement en dev-dependencies ?
Ce plan garantit que les fondations sont saines. Une fois la Scene rendue automatiquement par `app.render()`, l'ajout de toute nouvelle fonctionnalité (lumières, textures) deviendra une simple question d'ajout de données dans la structure de scène, sans modification de la boucle de rendu. Ce plan garantit que les fondations sont saines. Une fois la Scene rendue automatiquement par `app.render()`, l'ajout de toute nouvelle fonctionnalité (lumières, textures) deviendra une simple question d'ajout de données dans la structure de scène, sans modification de la boucle de rendu.
+12 -3
View File
@@ -1,3 +1,12 @@
---
type: Roadmap
title: WSG Engine Development Roadmap
description: Development roadmap for the WSG engine from prototype to full-featured 3D rendering engine
tags: [roadmap, development, planning, wsg-lib, 3d-rendering]
status: stable
generated: { by: human:jerome, at: 2026-07-31T00:00:00Z }
---
# Roadmap WSG — Prototype → Moteur Complet # Roadmap WSG — Prototype → Moteur Complet
> Basé sur l'architecture existante (ARCHI_APP, ARCHI_ARENES, ARCHI_CPU_GPU, ARCHI_RENDU). > Basé sur l'architecture existante (ARCHI_APP, ARCHI_ARENES, ARCHI_CPU_GPU, ARCHI_RENDU).
@@ -10,16 +19,16 @@
**Objectif** : Afficher un cube (ou autre mesh) 3D avec un éclairage Phong basique. **Objectif** : Afficher un cube (ou autre mesh) 3D avec un éclairage Phong basique.
### 1.1 Dépendances & Mathématiques ### 1.1 Dépendances & Mathématiques
- [ ] Ajouter `glam = "0.29"` en dépendance (`lib/Cargo.toml`) - [ ] Ajouter `glam = "0.33"` en dépendance (`lib/Cargo.toml`)
- [ ] Ajouter `slotmap = "1.0"` en dépendance - [ ] Ajouter `slotmap = "1.0"` en dépendance
- [ ] Créer module `math/` (ou `transform.rs`) : - [ ] Créer module `math/` (ou `transform.rs`) :
- [ ] Struct `Transform { translation: Vec3, rotation: Quat, scale: Vec3 }` - [ ] Struct `Transform { translation: Vec3, rotation: Quat, scale: Vec3 }`
- [ ] Méthode `to_matrix() -> Mat4` pour calculer la matrice locale - [ ] Méthode `to_matrix() -> Mat4` pour calculer la matrice locale
- [ ] Struct `Camera { position: Vec3, target: Vec3, up: Vec3 }` - [ ] Struct `Camera { position: Vec3, target: Vec3, up: Vec3 }` : resources/camera.rs
- [ ] Fonctions `view_matrix()` et `projection_matrix(fov, aspect, near, far)` - [ ] Fonctions `view_matrix()` et `projection_matrix(fov, aspect, near, far)`
### 1.2 Geometry & Mesh ### 1.2 Geometry & Mesh
- [ ] Créer struct `Geometry` : - [ ] Créer struct `Geometry` (math/geometry.rs) :
- [ ] `positions: Vec<[f32; 3]>` (obligatoire) - [ ] `positions: Vec<[f32; 3]>` (obligatoire)
- [ ] `indices: Option<Vec<u16>>` (optionnel) - [ ] `indices: Option<Vec<u16>>` (optionnel)
- [ ] `normals: Option<Vec<[f32; 3]>>` (pour Phong) - [ ] `normals: Option<Vec<[f32; 3]>>` (pour Phong)
@@ -1,15 +1,36 @@
# IAgent Documentation ---
type: Rule
title: Documentation Rules
description: Rules and guidelines for documentation in the WSG project, following OKF v0.2 specification
resource: https://github.com/wsg-project/wsg/blob/main/docs/rules/DOCUMENTATION.md
tags: [documentation, guidelines, standards]
sources: [{ ref: SPEC.md }]
verified: { by: "human:jerome", at: 2026-07-31T00:00:00Z }
status: active
stale_after: 2027-01-31T00:00:00Z
generated: { by: "human:jerome", at: 2026-07-31T00:00:00Z }
---
## Language # Documentation Rules
## Schema
All documentation follows the OKF v0.2 specification (see [SPEC.md](https://github.com/wsg-project/wsg/blob/main/docs/rules/SPEC.md)). This document defines project-specific rules for writing and maintaining code documentation.
## Conventions
### Language
All documentation is written in English; as a convention, the code itself uses English for variable names, function names, etc. All documentation is written in English; as a convention, the code itself uses English for variable names, function names, etc.
## Code Documentation ### Code Documentation
Every source file and configuration file must be systematically documented following the rules defined in this DOCUMENTATION.md file. Additionally, every directory must contain its own README.md file summarizing and explaining the module's organization at that level: what is the overall responsibility of the files grouped in this directory, which ones they are, and what each one does. Every source file and configuration file must be systematically documented following the rules defined in this DOCUMENTATION.md file. Additionally, every directory must contain its own README.md file summarizing and explaining the module's organization at that level: what is the overall responsibility of the files grouped in this directory, which ones they are, and what each one does.
We assume the reader has professional algorithmic knowledge but may not necessarily be a Rust specialist. The reader does know the project's domain — LLM logic, clients, and agents. Documentation should therefore be tailored for a professional developer who knows some programming languages (not necessarily Rust). We assume the reader has professional algorithmic knowledge but may not necessarily be a Rust specialist. The reader does know the project's domain — LLM logic, clients, and agents. Documentation should therefore be tailored for a professional developer who knows some programming languages (not necessarily Rust).
## Examples
### General Rule ### General Rule
Documentation must describe what is coded and what purpose it serves. A LLM reading the code and documentation should be able to verify whether: Documentation must describe what is coded and what purpose it serves. A LLM reading the code and documentation should be able to verify whether:
@@ -20,7 +41,7 @@ Documentation must describe what is coded and what purpose it serves. A LLM read
Each module or file must include documentation explaining the module's responsibility and how it interacts with other modules in the program, at least those within its own directory. This documentation must detail the main objects (Struct, Enum, Trait) manipulated in the module and the primary functions that carry the module's core logic. Each module or file must include documentation explaining the module's responsibility and how it interacts with other modules in the program, at least those within its own directory. This documentation must detail the main objects (Struct, Enum, Trait) manipulated in the module and the primary functions that carry the module's core logic.
## Within a File's Code ## Internal Steps
### Object and Function Headers ### Object and Function Headers
@@ -30,6 +51,6 @@ At the header of each object, describe what the object represents and its purpos
If an object or function presents a particularity or specific technical point, then a descriptive comment is inserted directly into the code body or function body. If a point of attention or technical point was described in the function header, then a comment in the code body reminds where this point is located. If an object or function presents a particularity or specific technical point, then a descriptive comment is inserted directly into the code body or function body. If a point of attention or technical point was described in the function header, then a comment in the code body reminds where this point is located.
## Documentation Maintenance ## Maintenance
The rules defined in this file are regularly applied across all code documentation to ensure consistency between code evolution and its documentation. The rules defined in this file are regularly applied across all code documentation to ensure consistency between code evolution and its documentation.
+54
View File
@@ -0,0 +1,54 @@
---
type: Specification
title: Open Knowledge Framework (OKF) v0.2 Specification
sources: [SPEC.md]
generated: true
verified: false
status: draft
stale_after: 2026-12-31
---
# Open Knowledge Framework v0.2 Summary
This document provides a concise overview of the OKF v0.2 specification as implemented in the WSG project. It aggregates the key concepts defined in the fragment files under `docs/rules/fragments/`.
## 1. Crosslinking and Paths (Fragment05)
- Local bundle links use the `@/` prefix.
- Paths are written without the `.md` extension.
- Enables a graph of interconcept relationships.
## 2. Provenance `sources` (Fragment06)
- `sources` records origin identifiers (files, URLs).
- Supports traceability and impact analysis.
## 3. Trust `generated` / `verified` (Fragment07)
- `generated: true` for automatically produced docs.
- `verified: true` only after human review.
## 4. Lifecycle `status` & `stale_after` (Fragment08)
- `status` values: `draft`, `current`, `deprecated`, `archived`.
- `stale_after` ISO8601 date triggers review.
## 5. Actor Convention (Fragment09)
- `actor` field follows `<type>/<name>` (e.g., `person/jdoe`).
- Provides attribution and accountability.
## 6. Attested Computation (§10) (Fragment10)
- `computation` describes a deterministic script and its arguments.
- Successful run allows promotion to `verified: true`.
## 7. Index Files (Fragment11)
- `index.md` lists bundle concepts for humans and tools.
- Must stay synchronized with actual content.
## 8. Log Files (Fragment12)
- `log.md` records timestamped, actoridentified changes.
- Enables audit trails and diff generation.
## 9. Changes from v0.1 (Fragment13)
- Introduced `stale_after`, `actor`, `computation` fields.
- Standardised boolean flags and crosslink syntax.
---
*All fragment files are stored under `docs/rules/fragments/` and should be kept in sync with this summary. Future revisions of the specification will update the `status` and `stale_after` fields accordingly.*
+1003
View File
File diff suppressed because it is too large Load Diff
+21
View File
@@ -0,0 +1,21 @@
---
type: Section
title: Motivation
---
# Motivation
The space of knowledge representation for AI agents is evolving quickly, and many incompatible conventions are emerging. OKF takes the position that knowledge is best represented in commonly accessible, established formats that are:
- **Readable** by humans without tooling.
- **Parseable** by agents without bespoke SDKs.
- **Diffable** in version control.
- **Portable** across tools, organizations, and time.
Increasingly, a knowledge corpus is not authored once and then read: it is **continuously written and maintained by agents**. When most concepts are machinegenerated, a consumer needs answers that a plain markdownplusfrontmatter convention does not make firstclass:
1. What was this created from, and how was it verified? (**provenance**)
2. How much should I trust it? (**trust**)
3. Is it still true? (**freshness**)
4. Is it the current version? (**lifecycle**)
5. Was this number produced the way we said it must be? (**attestation**)
+22
View File
@@ -0,0 +1,22 @@
---
type: Section
title: Terminology
---
# Terminology
- **Knowledge Bundle** (or **bundle**): a selfcontained, hierarchical collection of knowledge documents.
- **Concept**: a single unit of knowledge represented as one markdown document.
- **Concept ID**: the file path of the concept within the bundle, without the `.md` suffix.
- **Frontmatter**: a YAML metadata block at the top of a markdown file.
- **Body**: the markdown content following the frontmatter.
- **Link**: a standard markdown link used to express relationships between concepts.
- **Source**: a material a concept derives from, recorded in the `sources` frontmatter field.
- **Provenance**: the set of sources a concept derives from.
- **Credibility signal**: objective persource facts (author, usage_count, last_modified).
- **Actor**: identifier of who performed an action, using the convention `<producer>/<version>`, `human:<id>`, or `process:<id>`.
- **Trust tier**: level derived from the `verified` field (unverified, machineconfirmed, humanreviewed).
- **Attested Computation**: a concept (`type: Attested Computation`) that carries a sanctioned way to compute a value.
- **Executor**: runs a computation and returns a receipt.
- **Receipt**: evidence returned by an executor, inspected by an attester.
- **Attester**: deterministic code that validates a receipt.
@@ -0,0 +1,24 @@
---
type: Section
title: Bundle Structure
---
# Bundle Structure
A Knowledge Bundle is a self-contained, hierarchical collection of knowledge documents. The bundle root contains an `index.md` file that lists all concepts in the bundle. Each concept is a separate markdown file with its own frontmatter and body.
## Directory Layout
```
bundle-root/
├── index.md # Bundle-level index (conventional filename)
├── concept-a.md # Top-level concept
└── subdir/
└── concept-b.md # Nested concept; ID = "subdir/concept-b"
```
Concept IDs are the file path without `.md`. A concept at `bundle-root/subdir/concept-b.md` has ID `subdir/concept-b`.
## Index File
The `index.md` at the bundle root is a conventional entry point listing all top-level concepts. It serves as progressive disclosure for large bundles.
@@ -0,0 +1,45 @@
---
type: Section
title: Concept Documents
sources: [SPEC.md]
generated: true
verified: false
status: current
stale_after: 2026-12-31
---
# Concept Documents
A knowledge concept is a document containing metadata and content. It consists of two parts: **frontmatter** and **body**. The body is the main content.
## Frontmatter
Frontmatter is YAML enclosed between `---` delimiters at the start of the document, before any other text. All frontmatter keys MUST be lowercase.
### Required Fields
| Field | Type | Description |
|-------|------|-------------|
| `type` | string | Must be one of: `Rule`, `Section`, `Example`, `Template` |
| `title` | string | Human-readable title of the concept |
### Optional Fields
#### Provenance Family (`sources`)
List of URIs or paths identifying sources used to produce this document. Values may reference files, URLs, or external resources.
#### Trust Family (`generated`, `verified`)
- `generated`: boolean — whether the document was produced by an automated system
- `verified`: boolean — whether a human has reviewed the document's correctness
#### Lifecycle Family (`status`, `stale_after`)
- `status`: string — lifecycle status: `draft`, `current`, `deprecated`
- `stale_after`: date-string — after which this document should no longer be relied upon
### Conventions
- Unknown additional frontmatter entries MAY be included
- New conventional section headings can be added to bodies
+21
View File
@@ -0,0 +1,21 @@
---
type: Section
title: Cross-linking and Paths
sources: [SPEC.md]
generated: true
verified: false
status: current
stale_after: 2026-12-31
---
# Cross-linking and Paths
Concepts in a bundle can reference each other using paths relative to the bundle root. The path format is `bundle/path/to/concept` without the `.md` extension.
## Link Format
```markdown
See [concept-a](@/path/to/concept).
```
The `@/` prefix indicates a local bundle link. This allows concepts to form a graph of relationships rather than being isolated documents.
+23
View File
@@ -0,0 +1,23 @@
---
type: Section
title: Provenance (Sources)
sources: [SPEC.md]
generated: true
verified: false
status: current
stale_after: 2026-12-31
---
# Provenance (Sources)
The `sources` frontmatter field records the origin of a document. It is a list of identifiers (typically file names or URLs) that point to the original material used to create the concept.
## Usage
```yaml
sources:
- SPEC.md
- https://example.com/related-spec
```
Including sources ensures traceability, enables impact analysis when source material changes, and supports proper attribution.
+18
View File
@@ -0,0 +1,18 @@
---
type: Section
title: Trust (Generated & Verified)
sources: [SPEC.md]
generated: true
verified: false
status: current
stale_after: 2026-12-31
---
# Trust (Generated & Verified)
Two boolean flags express the trustworthiness of a document:
- `generated`: set to `true` when the document was created automatically (e.g., by a script or tool).
- `verified`: set to `true` only after a human reviewer has confirmed the content.
Both flags start as `true`/`false` respectively; they must be updated manually when verification occurs.
+18
View File
@@ -0,0 +1,18 @@
---
type: Section
title: Lifecycle (Status & Stale After)
sources: [SPEC.md]
generated: true
verified: false
status: current
stale_after: 2026-12-31
---
# Lifecycle (Status & Stale After)
Two fields describe a document's lifecycle:
- `status`: one of `draft`, `current`, `deprecated`, or `archived`.
- `stale_after`: an ISO8601 date after which the document should be reviewed.
These fields help automated tools decide when to flag a concept for revision.
@@ -0,0 +1,21 @@
---
type: Section
title: Actor Convention
sources: [SPEC.md]
generated: true
verified: false
status: current
stale_after: 2026-12-31
---
# Actor Convention
The `actor` frontmatter field records the identity that created or maintains a concept. It follows the pattern `<type>/<name>` where `<type>` is `person`, `organization`, or `automation`.
## Example
```yaml
actor: person/jdoe
```
Using a structured actor name enables automated attribution and accountability.
@@ -0,0 +1,23 @@
---
type: Section
title: Attested Computation (§10)
sources: [SPEC.md]
generated: true
verified: false
status: current
stale_after: 2026-12-31
---
# Attested Computation (§10)
The `computation` field records a deterministic computation that can be rerun to verify a documents content. It typically includes a reference to a script or function and its inputs.
## Example
```yaml
computation:
script: verify_hash.sh
args: ["{{file}}", "{{expected_hash}}"]
```
When the computation succeeds, the document can be marked `verified: true`.
+24
View File
@@ -0,0 +1,24 @@
---
type: Section
title: Index Files
sources: [SPEC.md]
generated: true
verified: false
status: current
stale_after: 2026-12-31
---
# Index Files
An `index.md` file at the root of a bundle lists the concepts it contains. It provides a table of contents for humans and a machinereadable list for tools.
## Example
```markdown
# Index
- [Concept A](@/concepts/a)
- [Concept B](@/concepts/b)
```
Index files should be kept in sync with the bundle's actual contents.
+21
View File
@@ -0,0 +1,21 @@
---
type: Section
title: Log Files
sources: [SPEC.md]
generated: true
verified: false
status: current
stale_after: 2026-12-31
---
# Log Files
A `log.md` file records incremental changes to a concept. Each entry includes a timestamp, the actor, and a short description of the modification.
## Example Entry
```markdown
- 2026-03-15T12:34:56Z person/jdoe: Updated description of the `status` field.
```
Log files enable audit trails and support automated diff generation.
+21
View File
@@ -0,0 +1,21 @@
---
type: Section
title: Changes from v0.1
sources: [SPEC.md]
generated: true
verified: false
status: current
stale_after: 2026-12-31
---
# Changes from v0.1
This section records the major updates introduced in version0.2 of the OKF specification compared to v0.1.
- Added `stale_after` field to support automated review scheduling.
- Introduced `actor` field for attribution of changes.
- Formalised `computation` field for attested reproducibility.
- Standardised frontmatter boolean flags `generated` and `verified`.
- Expanded crosslink syntax with the `@/` prefix.
These changes improve traceability, accountability, and automation support.
+141
View File
@@ -0,0 +1,141 @@
---
type: Architecture
title: wsg_lib Engine Architecture
description: Technical architecture and design principles of the wsg_lib rendering engine
tags: [architecture, rendering, graphics, wgpu, engine]
actor: person/jerome
sources: []
generated: { by: human:jerome, at: 2026-07-31T00:00:00Z }
verified: true
status: current
stale_after: 2027-01-31
---
# Architecture du Moteur wsg_lib
wsg_lib est un moteur de rendu modulaire basé sur wgpu. Il adopte une architecture à deux niveaux : une façade de haut niveau pour la productivité et un accès bas niveau pour un contrôle total.
## 1. Philosophie et Principes
- **Abstraction vs Transparence** : Le moteur masque la complexité (wgpu, winit, gestion des Frame) via `App`, tout en exposant les briques élémentaires pour les utilisateurs avancés.
- **Architecture GPU-Driven** : Le CPU est le cerveau logique (gestion de la scène, IA, réseau), le GPU est l'exécutant visuel. Le moteur délègue au GPU le calcul des World Matrices, le Frustum Culling et la génération des listes de dessin indirectes — évitant ainsi les goulets d'étranglement PCIe.
- **Pipeline à deux passes** : Chaque frame suit un ordre strict : **Compute Pass** (calculs GPU) → **Render Pass** (dessin indirect). Les barrières de mémoire sont gérées automatiquement par le driver.
- **Ressources persistantes en VRAM** : Les buffers essentiels (Transform, Matrix, BoundingBox, Indirect Draw) vivent d'une frame à l'autre sans redescendre vers le CPU.
> **Note sur la synchronisation** : La première itération utilise un **single buffer** pour les buffers Transform et Matrix (voir §4B). Le double buffering n'est pas nécessaire tant que `desired_maximum_frame_latency` ≥ 3 ou que le moteur fonctionne en FIFO avec une latence de ≥ 2 frames — dans ce cas, le GPU est toujours au moins 2 frames derrière, éliminant tout risque de collision CPU/GPU. Le double buffering sera ajouté uniquement si le moteur atteint des fréquences élevées (> 90 fps) où le CPU peut écrire une frame pendant que le GPU lit encore la précédente.
- **Lecture seule pendant render()** : La Scene est immuable durant le Render. L'utilisateur ne modifie que dans `update()` ; toute tentative de mutation pendant le rendu bloque les données du GPU.
- **Pipeline Cache** : Les shaders et pipelines sont compilés une fois puis réutilisés via `Arc`. Aucun readback (`map_async`) n'est effectué sauf débug critique.
## 2. Organisation des Modules (`lib/src/`)
- **`core/`** : Plomberie système (`Context`, `Renderer`, `Frame`). Accès bas niveau.
- **`pipeline/`** : `PipelineCache` pour la gestion des états GPU et shaders.
- **`resources/`** : Données (`Mesh`, `Material`, `Vertex`).
- **`scene/`** : Hiérarchie et stockage des objets à visualiser (Entités, Transformations).
- **`shaders/`** : Assets WGSL.
- **`utils/`** : Utilitaires transverses.
## 3. Interfaces de Haut Niveau (`App` & `AppHandler`)
### L'objet `App`
La façade `App` orchestre la boucle de jeu. Elle encapsule :
- Le cycle de vie de la fenêtre.
- La boucle d'événements.
- La gestion automatique des Frame (acquisition et présentation).
### Le trait `AppHandler`
L'utilisateur implémente ce trait pour définir la logique métier. Les deux méthodes sont appelées **dans l'ordre strict** à chaque frame :
```rust
pub trait AppHandler {
// Phase Update — écriture des Transform bruts (CPU → GPU via buffer mappé).
// Seules les données logiques changent ici (position, rotation, échelle).
fn update(&mut self, _app: &mut App) {}
// Phase Compute + Render — déclenche un Compute Pass puis un Render Pass.
// La Scene est en lecture seule : aucun état métier ne doit être modifié.
fn render(&mut self, app: &mut App);
}
```
- **`update()`** : appelé en premier. L'utilisateur peut modifier librement la scène (transformations, ajout/suppression d'entités). Ces modifications sont synchronisées vers le GPU via un **single buffer** Transform avant la passe de calcul.
- **`render()`** : appelé après. Il ne sert qu'à injecter du rendu personnalisé (debug, HUD, etc.). La Scene reste immuable : aucune mutation d'état métier.
## 4. Workflow et Cycle de Vie
### A. Initialisation (Configuration)
- **Shaders** : Chargés avant la renderloop.
- **PipelineCache** : Enregistre les shaders.
- **Matériaux** : Créés avec un shader associé. Un mesh sans matériau explicite utilise `basic_shader` par défaut.
- **Scene** : Assemblage des objets. L'utilisateur peuple la scène via `app.scene`.
### B. Boucle de Rendu — Pipeline GPU-Driven
Le moteur gère la renderloop interne via un pipeline à **deux passes séquentielles** :
```
[ CPU : Envoi des Transforms bruts ]
[ Pass 1 : Compute (World Matrices + Frustum Culling + Indirect Draw Buffer) ]
↓ (Barrière de mémoire automatique par le driver)
[ Pass 2 : Render (Draw Indexed Indirect basé sur les objets visibles) ]
```
Étape par étape :
1. **Update** (`AppHandler::update`) — L'utilisateur modifie la scène (transformations, entités). Ces changements sont synchronisés vers le GPU via un **single buffer** Transform avant la passe de calcul.
> La synchronisation est assurée par le pipeline wgpu : `queue.submit()` après le compute pass garantit que les données Transform sont valides avant le render pass suivant. Aucun double buffering n'est nécessaire tant que la latence maximale de la surface (via `desired_maximum_frame_latency`) est ≥ 3.
2. **Compute Pass** — Un compute shader lit les Transform bruts, calcule les World Matrices finales, effectue le Frustum Culling par AABB, et remplit l'Indirect Draw Buffer avec les identifiants des objets visibles.
3. **Render Pass** — Le CPU émet une unique commande `draw_indexed_indirect`. Le GPU pioche dans l'Indirect Draw Buffer et dessine uniquement les objets visibles, sans intervention du CPU.
4. **Présentation** — La surface est présentée à l'écran.
L'ordre d'appel des méthodes sur le `CommandEncoder` (`begin_compute_pass` puis `begin_render_pass`) garantit l'exécution séquentielle. Les barrières de mémoire entre passes sont insérées automatiquement par le pilote.
#### Ressources VRAM persistantes (d'une frame à l'autre)
| Buffer | Rôle | Type wGPU | Direction du flux |
|--------|------|-----------|-------------------|
| Transform Buffer | Positions/rotations/échelles brutes | Storage Buffer | CPU → GPU |
| Matrix Buffer | World Matrices finales calculées | Storage Buffer | GPU (Calculé) → GPU (Lu par Render) |
| Bounding Box Buffer | AABB de chaque mesh pour culling | Storage Buffer | CPU → GPU (Statique) |
| Indirect Draw Buffer | Liste dynamique des objets à dessiner | Indirect + Storage | GPU (Rempli par Compute) → GPU (Lu par Render) |
> **Synchronisation single buffer** : Les buffers Transform et Matrix utilisent un **single buffer** en phase initiale. Le CPU écrit dans le buffer pendant `update()`, puis le compute shader lit les données au frame suivant via `queue.submit()` qui garantit la séquence d'exécution. Cette approche fonctionne correctement tant que la surface a une latence maximale ≥ 2 frames (configuré via `desired_maximum_frame_latency`). Le double buffering sera ajouté uniquement si des artefacts visuels apparaissent à haute fréquence (typiquement > 90 fps sur machines rapides).
Toutes ces données vivent en VRAM — aucun readback (`map_async`) n'est effectué sauf débug critique. Le CPU fait confiance à sa propre structure de données initiale pour la logique métier.
## 5. Accès Avancé
Les utilisateurs souhaitant ignorer l'abstraction `App` peuvent accéder directement à :
- `wsg_lib::core::Context` et `Renderer` pour gérer manuellement les Compute Pass et RenderPass.
- `wsg_lib::pipeline::PipelineCache` pour des besoins de shaders personnalisés (compute + render).
- `winit` pour la gestion précise des événements système.
## 6. Structure des données (pour LLM)
```
App (Facade) -> Scene (Conteneur) -> Entities -> Mesh + Material (Shader)
|
+-> Renderer (WGPU)
├── Compute Pass : World Matrices + Frustum Culling → Indirect Draw Buffer
└── Render Pass : draw_indexed_indirect (objets visibles uniquement)
VRAM persistante : Transform Buffer → Matrix Buffer → BoundingBox Buffer → Indirect Draw Buffer
Single buffer (phase initiale) : Update écrit, Compute lit au frame suivant — garanti par queue.submit()
[À venir] Double buffering : buffers Transform/Matrix dupliqués + swap entre frames
```
## Notes pour l'implémentation future
- **`render()` ne prend pas de scène en argument** — elle déclenche automatiquement le Compute Pass puis le Render Pass sur la scène actuelle. Pour injecter du rendu personnalisé, utiliser ce point d'extension sans modifier l'état métier.
- **Trait `AppHandler`** : Le `update()` est le seul endroit où muter la scène. La `Scene` peut être stockée directement dans l'implémentation (`MyGame { scene: Scene, ... }`) ou passée via argument selon les besoins ergonomiques.
- **`PipelineCache`** : Invisible pour l'utilisateur standard lors de la création d'un `Material`, mais accessible publiquement pour shaders compute personnalisés et pipelines avancés.
- **Compute shader par défaut** : Un compute shader intégré gère le calcul des World Matrices et le Frustum Culling. Les utilisateurs avancés peuvent le remplacer entièrement via `PipelineCache`.
- **Synchronisation** : Toujours appeler `begin_compute_pass` avant `begin_render_pass` sur le même `CommandEncoder`. Les barrières entre passes sont automatiques — ne jamais insérer de barrière manuelle sauf besoin critique.
- **Synchronisation single buffer (phase initiale)** : La séquence `queue.submit()` après chaque compute pass garantit que les données Transform sont valides avant le render pass suivant. Aucun conflit de lecture/écriture n'est possible tant que `desired_maximum_frame_latency` ≥ 3.
- **Double Buffering (future migration)** : Sera implémenté sur les buffers Transform et Matrix seulement, pas sur BoundingBox ni Indirect Draw. Le switch se résume à : dupliquer ces deux buffers, ajouter une méthode `swap()` appelée dans `AboutToWait`, modifier les bind groups pour pointer vers l'index courant. Pas besoin de refonte architecturale.
@@ -1,3 +1,16 @@
---
type: Technical Specification
title: Generational Arena Resource Management with slotmap
description: Technical specification for efficient and safe resource management using generational arenas implemented via the slotmap crate
tags: [architecture, resources, performance, safety, slotmap, arena]
actor: person/jerome
sources: []
generated: { by: human:jerome, at: 2026-07-31T00:00:00Z }
verified: true
status: current
stale_after: 2027-01-31
---
# Fiche Technique : Gestion des Ressources avec des Arènes Générationalles (`slotmap`) # Fiche Technique : Gestion des Ressources avec des Arènes Générationalles (`slotmap`)
Cette fiche technique détaille l'implémentation recommandée pour gérer efficacement et en toute sécurité les ressources (maillages, textures, matériaux, lumières, etc.) au sein du moteur graphique WSG. Nous utilisons le concept d'**arène générationalle**, implémenté via la crate `slotmap`, pour bénéficier d'IDs stables, de performances optimales, de sécurité accrue et de fonctionnalités avancées comme les `SecondaryMap`. Cette fiche technique détaille l'implémentation recommandée pour gérer efficacement et en toute sécurité les ressources (maillages, textures, matériaux, lumières, etc.) au sein du moteur graphique WSG. Nous utilisons le concept d'**arène générationalle**, implémenté via la crate `slotmap`, pour bénéficier d'IDs stables, de performances optimales, de sécurité accrue et de fonctionnalités avancées comme les `SecondaryMap`.
@@ -1,3 +1,16 @@
---
type: Technical Specification
title: GPU-Driven 3D Rendering Architecture with wGPU
description: Technical specification for GPU-driven 3D rendering architecture using wgpu, focusing on CPU-GPU workload distribution and performance optimization
tags: [architecture, rendering, gpu, cpu, performance, wgpu]
actor: person/jerome
sources: []
generated: { by: human:jerome, at: 2026-07-31T00:00:00Z }
verified: true
status: current
stale_after: 2027-01-31
---
Architecture de Rendu 3D GPU-Driven avec wGPU : Architecture de Rendu 3D GPU-Driven avec wGPU :
Bonnes Pratiques & Guide d'Implémentation Bonnes Pratiques & Guide d'Implémentation
@@ -29,7 +42,7 @@ L'exécution des tâches s'appuie sur une structure séquentielle stricte au sei
``` ```
Étape par étape : Étape par étape :
- Mise à jour CPU (Minimaliste) : Le CPU écrit les transformations brutes (Transform) modifiées dans un buffer GPU mappé (via un mécanisme de Double Buffering pour éviter les conflits de lecture/écriture). - Mise à jour CPU (Minimaliste) : Le CPU écrit les transformations brutes (Transform) modifiées dans un buffer GPU mappé (single buffer en phase initiale — la synchronisation est assurée par `queue.submit()` qui garantit la séquence d'exécution). Double buffering sera ajouté uniquement si des artefacts apparaissent à haute fréquence (> 90 fps).
- Pass de Calcul (Compute Pass) : - Pass de Calcul (Compute Pass) :
- Calcul des World Matrices : Un compute shader lit les transformations brutes et génère la matrice 4x4 finale pour chaque mesh. - Calcul des World Matrices : Un compute shader lit les transformations brutes et génère la matrice 4x4 finale pour chaque mesh.
- Frustum Culling GPU : Le même compute shader (ou un compute pass dédié) compare la Bounding Box (AABB) de chaque objet avec les plans de la caméra (matrice de projection/vue). - Frustum Culling GPU : Le même compute shader (ou un compute pass dédié) compare la Bounding Box (AABB) de chaque objet avec les plans de la caméra (matrice de projection/vue).
@@ -1,3 +1,16 @@
---
type: Technical Specification
title: Rendering Architecture: Update/Render Cycle and Data Management
description: Technical specification for the rendering architecture of wsg_lib, defining strategies for mutability and data management to maximize performance and memory safety in Rust
tags: [architecture, rendering, rust, performance, memory-safety]
actor: person/jerome
sources: []
generated: { by: human:jerome, at: 2026-07-31T00:00:00Z }
verified: true
status: current
stale_after: 2027-01-31
---
# Architecture de Rendu : Cycle Update/Render et Gestion des Données # Architecture de Rendu : Cycle Update/Render et Gestion des Données
Ce document définit la stratégie de gestion de la mutabilité et des données du moteur wsg_lib, conçue pour maximiser la performance et garantir la sécurité mémoire via Rust. Ce document définit la stratégie de gestion de la mutabilité et des données du moteur wsg_lib, conçue pour maximiser la performance et garantir la sécurité mémoire via Rust.
+15
View File
@@ -1,3 +1,16 @@
---
type: Technical Specification
title: Frame Loop Architecture
description: Technical specification for the frame loop architecture in wsg_lib, detailing the immutable frame lifetime cycle and resource management
tags: [architecture, rendering, frame-loop, gpu, wgpu]
actor: person/jerome
sources: []
generated: { by: human:jerome, at: 2026-07-31T00:00:00Z }
verified: true
status: current
stale_after: 2027-01-31
---
# La Boucle de Rendu (Frame Loop) # La Boucle de Rendu (Frame Loop)
Pour afficher quelque chose, nous suivons un cycle immuable appelé la Frame Lifetime. Dans ton `main.rs` (l'orchestrateur), le flux est désormais le suivant : Pour afficher quelque chose, nous suivons un cycle immuable appelé la Frame Lifetime. Dans ton `main.rs` (l'orchestrateur), le flux est désormais le suivant :
@@ -27,4 +40,6 @@ Avec notre nouvelle architecture "Atelier", la distinction est devenue encore pl
| CommandEncoder | Par-Frame | Ton "carnet de notes" temporaire pour les ordres du GPU. | | CommandEncoder | Par-Frame | Ton "carnet de notes" temporaire pour les ordres du GPU. |
| TextureView | Par-Frame | Fenêtre temporaire sur la texture active du swapchain. | | TextureView | Par-Frame | Fenêtre temporaire sur la texture active du swapchain. |
> **Ressources GPU persistantes (single buffer)** : Les buffers Transform et Matrix sont stockés en VRAM avec un **single buffer** en phase initiale. Le CPU écrit pendant `update()`, le compute shader lit au frame suivant via la séquence garantie par `queue.submit()`. Double buffering sera ajouté uniquement si des artefacts visuels apparaissent à haute fréquence.
--- ---
+217
View File
@@ -0,0 +1,217 @@
Diagnose log at 2026-07-31T18:48:16Z
AppPath: /usr/local/bin/git-credential-manager
InstallDir: /usr/local/share/gcm-core/
Version: 2.6.1+786ab03440ddc82e807a97c0e540f5247e44cec6
------------
Diagnostic: Environment
Skipped: False
Success: True
Exception: None
Log:
OSType: Linux
OSVersion: Ubuntu 24.04.4 LTS
Reading environment variables... OK
Variables:
GSM_SKIP_SSH_AGENT_WORKAROUND=true
ZED_TERM=true
GEMINI_API_KEY=AIzaSyAcgradZn-Y0VthnobNSA4o82N7X5bL_8k
GDK_BACKEND=wayland,x11
QTWEBENGINE_DICTIONARIES_PATH=/usr/share/hunspell-bdic/
ANDROID_HOME=/home/jerome/Android/Sdk
COSMIC_PANEL_ANCHOR=Left
_=/usr/bin/git
ALACRITTY_WINDOW_ID=4294967349
XDG_SESSION_DESKTOP=cosmic
QT_ACCESSIBILITY=1
COSMIC_PANEL_SIZE=L
HOME=/home/jerome
ANDROID_NDK_HOME=/home/jerome/Android/Sdk/ndk/29.0.14206865
GTK_IM_MODULE=ibus
JAVA_HOME=/home/jerome/android-studio-panda2-linux/android-studio/jbr
PATH=/usr/lib/git-core:/home/jerome/.local/bin:/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/home/jerome/android-studio-panda2-linux/android-studio/jbr/bin:/usr/local/cuda/bin:/home/jerome/.opencode/bin:/home/jerome/.bun/bin:/run/user/1000/fnm_multishells/71636_1785523522033/bin:/home/jerome/.local/share/fnm:/home/jerome/.local/bin:/home/jerome/.local/bin:/home/jerome/.local/bin:/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/home/jerome/android-studio-panda2-linux/android-studio/jbr/bin:/usr/local/cuda/bin:/home/jerome/.opencode/bin:/home/jerome/.bun/bin:/run/user/1000/fnm_multishells/13158_1785514517963/bin:/home/jerome/.local/share/fnm:/home/jerome/.local/bin:/home/jerome/.local/bin:/home/jerome/.local/bin:/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/home/jerome/android-studio-panda2-linux/android-studio/jbr/bin:/usr/local/cuda/bin:/home/jerome/.opencode/bin:/home/jerome/.bun/bin:/run/user/1000/fnm_multishells/12525_1785514517360/bin:/home/jerome/.local/share/fnm:/home/jerome/.nvm/versions/node/v22.20.0/bin:/home/jerome/.local/bin:/home/jerome/.cargo/bin:/home/jerome/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin:/home/jerome/.lmstudio/bin:/usr/local/go/bin:/home/jerome/Android/Sdk/emulator:/home/jerome/Android/Sdk/platform-tools:/home/jerome/Android/Sdk/cmdline-tools/latest/bin:/home/jerome/Android/Sdk/build-tools:/home/jerome/.lmstudio/bin:/home/jerome/.lmstudio/bin:/usr/local/go/bin:/home/jerome/Android/Sdk/emulator:/home/jerome/Android/Sdk/platform-tools:/home/jerome/Android/Sdk/cmdline-tools/latest/bin:/home/jerome/Android/Sdk/build-tools:/home/jerome/.lmstudio/bin:/home/jerome/.lmstudio/bin:/usr/local/go/bin:/home/jerome/Android/Sdk/emulator:/home/jerome/Android/Sdk/platform-tools:/home/jerome/Android/Sdk/cmdline-tools/latest/bin:/home/jerome/Android/Sdk/build-tools:/home/jerome/.lmstudio/bin
TERM=xterm-256color
QT_IM_MODULE=ibus
X_PRIVILEGED_WAYLAND_SOCKET=114
FNM_ARCH=x64
CLUTTER_IM_MODULE=ibus
LD_LIBRARY_PATH=/usr/local/cuda/lib64:/usr/local/cuda/lib64:/usr/local/cuda/lib64
XDG_VTNR=2
FNM_RESOLVE_ENGINES=true
DEBUGINFOD_URLS=https://debuginfod.ubuntu.com
GIT_TRACE2_PARENT_SID=d6e89d30-0e68-496d-b026-b9696e2d470f
ALBERT_API_KEY=sk-eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjozNDYsInRva2VuX2lkIjo0NDgyLCJleHBpcmVzX2F0IjoxNzkzMjI4NDAwfQ.mRlU8oR4oNHY5QgST29bM9kaJ21vM0yhwGsUW0QVwpM
COLORTERM=truecolor
GDMSESSION=cosmic
COSMIC_PANEL_PADDING_OVERLAP=0.5
INFOPATH=/home/linuxbrew/.linuxbrew/share/info:/home/linuxbrew/.linuxbrew/share/info:/home/linuxbrew/.linuxbrew/share/info:
MOZ_ENABLE_WAYLAND=1
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
LESSCLOSE=/usr/bin/lesspipe %s %s
USER=jerome
GIT_EXEC_PATH=/usr/lib/git-core
PANEL_NOTIFICATIONS_FD=21
GTK_MODULES=gail:atk-bridge
SHLVL=1
QT_ENABLE_HIGHDPI_SCALING=1
XDG_SEAT=seat0
NVM_DIR=/home/jerome/.nvm
IM_CONFIG_CHECK_ENV=1
NVM_CD_FLAGS=
WINDOWID=4294967349
XDG_CURRENT_DESKTOP=COSMIC
COSMIC_PANEL_SPACING=4
FNM_VERSION_FILE_STRATEGY=local
X_MINIMIZE_APPLET=false
XDG_SESSION_CLASS=user
FNM_LOGLEVEL=info
QT_QPA_PLATFORMTHEME=qt6ct
SHELL=/bin/bash
COSMIC_PANEL_OUTPUT=DP-1
BUN_INSTALL=/home/jerome/.bun
FNM_MULTISHELL_PATH=/run/user/1000/fnm_multishells/71636_1785523522033
IM_CONFIG_PHASE=1
QT_AUTO_SCREEN_SCALE_FACTOR=1
LIBVIRT_DEFAULT_URI=qemu:///system
LOGNAME=jerome
USERNAME=jerome
XDG_CONFIG_DIRS=/etc/xdg/xdg-cosmic:/etc/xdg
NVM_BIN=/home/jerome/.nvm/versions/node/v22.20.0/bin
DCONF_PROFILE=/usr/share/dconf/profile/cosmic
XMODIFIERS=@im=ibus
LANG=fr_FR.UTF-8
TERM_PROGRAM_VERSION=1.13.1+stable.332.00bd72e7838f4b875a913cd112b47a0ebe1ca62b
DESKTOP_SESSION=cosmic
HOMEBREW_PREFIX=/home/linuxbrew/.linuxbrew
WAYLAND_DISPLAY=wayland-1
ZED_ENVIRONMENT=worktree-shell
XDG_SESSION_ID=2
PWD=/home/jerome/scripts/rust/wsg
NVM_INC=/home/jerome/.nvm/versions/node/v22.20.0/include/node
FNM_DIR=/home/jerome/.local/share/fnm
IUT_API_KEY=eviv-78bulgroz-78
HOMEBREW_CELLAR=/home/linuxbrew/.linuxbrew/Cellar
LESSOPEN=| /usr/bin/lesspipe %s
XDG_RUNTIME_DIR=/run/user/1000
TERM_PROGRAM=zed
COSMIC_PANEL_BACKGROUND=ThemeDefault
DISPLAY=:1
FNM_COREPACK_ENABLED=false
XDG_SESSION_TYPE=wayland
OLDPWD=/home/jerome
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=00:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.avif=01;35:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:*~=00;90:*#=00;90:*.bak=00;90:*.crdownload=00;90:*.dpkg-dist=00;90:*.dpkg-new=00;90:*.dpkg-old=00;90:*.dpkg-tmp=00;90:*.old=00;90:*.orig=00;90:*.part=00;90:*.rej=00;90:*.rpmnew=00;90:*.rpmorig=00;90:*.rpmsave=00;90:*.swp=00;90:*.tmp=00;90:*.ucf-dist=00;90:*.ucf-new=00;90:*.ucf-old=00;90:
_JAVA_AWT_WM_NONREPARENTING=1
FNM_NODE_DIST_MIRROR=https://nodejs.org/dist
XDG_DATA_DIRS=/usr/share/cosmic:/home/jerome/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop
COSMIC_PANEL_NAME=Dock
HOMEBREW_REPOSITORY=/home/linuxbrew/.linuxbrew/Homebrew
SSH_AUTH_SOCK=/run/user/1000/gcr/ssh
QT_QPA_PLATFORM=wayland;xcb
------------
Diagnostic: File system
Skipped: False
Success: True
Exception: None
Log:
Temporary directory is '/tmp/'...
Checking basic file I/O...
Writing to temporary file '/tmp/4d2c46a5985dd9e274cc199e'... OK
Reading from temporary file '/tmp/4d2c46a5985dd9e274cc199e'... OK
Deleting temporary file '/tmp/4d2c46a5985dd9e274cc199e'... OK
Testing IFileSystem instance...
UserHomePath: /home/jerome
UserDataDirectoryPath: /home/jerome/.gcm
GetCurrentDirectory(): /home/jerome/scripts/rust/wsg
------------
Diagnostic: Networking
Skipped: False
Success: True
Exception: None
Log:
Checking networking and HTTP stack...
Creating HTTP client... OK
IsNetworkAvailable: True
Sending HEAD request to http://example.com...Sending HEAD request to https://example.com... OK
OK
Acquiring free TCP port... OK
Testing local HTTP loopback connections...
Creating new HTTP listener for http://localhost:44671/... OK
Waiting for loopback connection... OK
Writing response... OK
Waiting for response data... OK
Loopback connection data OK
------------
Diagnostic: Git
Skipped: False
Success: True
Exception: None
Log:
Getting Git version... OK
Git version is '2.43.0'
Locating current repository...Git repository at '/home/jerome/scripts/rust/wsg/.git'
OK
Listing all Git configuration... OK
Git configuration:
file:/home/jerome/.gitconfig credential.helper=
file:/home/jerome/.gitconfig credential.helper=/usr/local/bin/git-credential-manager
file:/home/jerome/.gitconfig credential.credentialstore=secretservice
file:/home/jerome/.gitconfig credential.https://dev.azure.com.usehttppath=true
file:/home/jerome/.gitconfig user.email=jerome.bousquie@ut-capitole.fr
file:/home/jerome/.gitconfig user.name=Jérôme Bousquié
file:/home/jerome/.gitconfig credential.https://codeberg.org.provider=generic
file:/home/jerome/.gitconfig credential.https://git.iut-rodez.fr.provider=generic
file:.git/config core.repositoryformatversion=0
file:.git/config core.filemode=true
file:.git/config core.bare=false
file:.git/config core.logallrefupdates=true
file:.git/config remote.origin.url=https://git.iut-rodez.fr/jerome/wsg.git
file:.git/config remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
file:.git/config branch.main.remote=origin
file:.git/config branch.main.merge=refs/heads/main
------------
Diagnostic: Credential storage
Skipped: False
Success: True
Exception: None
Log:
ICredentialStore instance is of type: CredentialStore
Writing test credential... OK
Reading test credential... OK
Deleting test credential... OK
------------
Diagnostic: Microsoft authentication (AAD/MSA)
Skipped: False
Success: True
Exception: None
Log:
Broker is not enabled.
Flow type is: Auto
Gathering MSAL token cache data... OK
CacheDirectory: /home/jerome/.local/.IdentityService
CacheFileName: msal.cache
CacheFilePath: /home/jerome/.local/.IdentityService/msal.cache
KeyringCollection:
KeyringSchemaName:
KeyringSecretLabel:
KeyringAttribute1: (,)
KeyringAttribute2: (,)
Creating cache helper... OK
Verifying MSAL token cache persistence... OK
------------
Diagnostic: GitHub API
Skipped: False
Success: True
Exception: None
Log:
Using 'https://github.com/' as API target.
Querying '/meta' endpoint... OK
+2
View File
@@ -11,6 +11,8 @@ wgpu = "30.0.0" # Vérifiez la version la plus récente
winit = "0.29" # For window management — pinned to match examples winit = "0.29" # For window management — pinned to match examples
thiserror = "2" thiserror = "2"
bytemuck = { version = "1.25.0", features = ["derive"] } bytemuck = { version = "1.25.0", features = ["derive"] }
glam = "0.33"
slotmap = "1.0"
[dev-dependencies] [dev-dependencies]
pollster = { version="0.4.0", features = ["macro"] } pollster = { version="0.4.0", features = ["macro"] }
+1
View File
@@ -32,6 +32,7 @@ pub mod pipeline;
pub mod resources; pub mod resources;
pub mod scene; pub mod scene;
pub mod utils; pub mod utils;
pub mod math;
/// Re-export of the high-level application facade for convenient top-level access. /// Re-export of the high-level application facade for convenient top-level access.
/// Users create App instances via `AppBuilder`, then call `.run(handler)` to start the application. /// Users create App instances via `AppBuilder`, then call `.run(handler)` to start the application.
+28
View File
@@ -0,0 +1,28 @@
//! # Geometry Module
//!
//! Defines the `Geometry` struct for storing vertex data of 3D meshes.
//! This module handles the core geometric representation used by meshes.
//!
//! ## Usage
//! - Stores vertex attributes (positions, normals, UVs)
//! - Used by `Mesh` to define its vertex data
//! - Passed to shaders for rendering
//!
//! ## Related Types
//! - `Geometry`: Main struct for vertex data storage
//! - Fields: positions, normals, uvs, indices
/// Represents the geometric data of a 3D mesh.
///
/// This struct stores the core vertex attributes that define a mesh's shape.
#[derive(Debug, Clone)]
pub struct Geometry {
/// Vertex positions as an array of 3D coordinates
pub positions: Vec<[f32; 3]>,
/// Optional vertex normals for lighting calculations
pub normals: Option<Vec<[f32; 3]>>,
/// Optional texture coordinates for UV mapping
pub uvs: Option<Vec<[f32; 2]>>,
/// Optional indices for indexed rendering
pub indices: Option<Vec<u16>>,
}
+23
View File
@@ -0,0 +1,23 @@
//! # Math Module — Geometric and Transformation Utilities
//!
//! Provides core mathematical types and utilities for 3D graphics operations, including:
//! - `Transform` for object positioning, rotation, and scaling
//! - `Camera` for view and projection matrix calculations
//! - `Geometry` for mesh vertex data representation
//!
//! ## Interaction with Other Modules
//! - `scene::Scene` uses `Transform` to manage entity positions
//! - `renderer::Renderer` uses `Transform` and `Camera` to compute matrices for shaders
//! - `resources::Mesh` stores vertex data in `Geometry` format
//!
//! ## Files
//! - `transform.rs`: Defines the `Transform` struct and its conversion to matrix form
//! - `geometry.rs`: Defines the `Geometry` struct for mesh data storage
//! - `camera.rs`: Defines the `Camera` struct and view/projection matrix calculations
pub mod transform;
pub mod geometry;
// Re-exports
pub use transform::Transform;
pub use geometry::Geometry;
+45
View File
@@ -0,0 +1,45 @@
//! # Transform Module
//!
//! Defines the `Transform` struct for representing object transformations in 3D space,
//! including translation, rotation, and scale. Also provides functionality to convert
//! the transform into a 4x4 matrix for use in shaders.
//!
//! ## Usage
//! - Used by `Scene` entities to define their position in the world
//! - Converted to `Mat4` for MVP matrix calculations in the renderer
//!
//! ## Related Types
//! - `Transform`: Core struct for position/rotation/scale
//! - `to_matrix()`: Converts transform to a 4x4 matrix
use glam::{Vec3, Quat, Mat4};
/// Represents a 3D transformation with translation, rotation, and scale.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Transform {
/// Translation vector in 3D space
pub translation: Vec3,
/// Rotation as a quaternion
pub rotation: Quat,
/// Scale factors along X, Y, Z axes
pub scale: Vec3,
}
impl Transform {
/// Creates a new identity transform.
pub fn identity() -> Self {
Self {
translation: Vec3::ZERO,
rotation: Quat::IDENTITY,
scale: Vec3::ONE,
}
}
/// Converts the transform into a 4x4 transformation matrix.
///
/// # Returns
/// A `Mat4` representing the transformation matrix
pub fn to_matrix(&self) -> Mat4 {
Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation)
}
}
+58
View File
@@ -0,0 +1,58 @@
//! # Camera Module
//!
//! Defines the `Camera` struct and related functionality for 3D viewing.
//! Supports different camera types and projection configurations.
//!
//! ## Usage
//! - Used by `Renderer` to compute view and projection matrices
//! - Configurable for perspective and orthographic projections
//! - Supports FPS-style and orbital movement patterns
//!
//! ## Related Types
//! - `Camera`: Main struct for camera configuration
//! - `view_matrix()`: Computes the view matrix
//! - `projection_matrix()`: Computes the projection matrix
use glam::{Vec3, Mat4};
/// Represents a 3D camera for viewing the scene.
///
/// The camera defines the viewpoint and projection settings for rendering.
#[derive(Debug, Clone)]
pub struct Camera {
/// Position of the camera in world space
pub position: Vec3,
/// Target point the camera is looking at
pub target: Vec3,
/// Up vector defining the camera's orientation
pub up: Vec3,
}
impl Camera {
/// Creates a new camera with specified position, target, and up vector.
pub fn new(position: Vec3, target: Vec3, up: Vec3) -> Self {
Self { position, target, up }
}
/// Computes the view matrix for this camera.
///
/// # Returns
/// A `Mat4` representing the view transformation matrix
pub fn view_matrix(&self) -> Mat4 {
Mat4::look_at_rh(self.position, self.target, self.up)
}
/// Computes the projection matrix for this camera.
///
/// # Parameters
/// - `fov`: Field of view in radians
/// - `aspect`: Aspect ratio of the viewport
/// - `near`: Near clipping plane distance
/// - `far`: Far clipping plane distance
///
/// # Returns
/// A `Mat4` representing the projection transformation matrix
pub fn projection_matrix(&self, fov: f32, aspect: f32, near: f32, far: f32) -> Mat4 {
Mat4::perspective_rh_gl(fov, aspect, near, far)
}
}