refactor examples

This commit is contained in:
Jérôme Bousquié
2026-09-25 10:19:24 +02:00
parent ab3f056dbb
commit 35aeb769a8
37 changed files with 3430 additions and 457 deletions
+245 -17
View File
@@ -1,23 +1,251 @@
# Examples
# Exemples WSG
Each `.rs` file in this directory is a **standalone example** auto-discovered by Cargo
(`cargo build -p wsg-lib --examples`). To run an example:
Chaque exemple est autonome et illustre **un effet ou une fonctionnalité** spécifique
de la bibliothèque. Tous utilisent l'API déclarative (`AppBuilder` + `AppHandler`).
```bash
cargo run -p wsg-lib --example <name>
## Lancer un exemple
```sh
cargo run -p wsg-lib --example <nom>
```
| Example | Command | Description |
|---------|---------|-------------|
| `demo` | `cargo run -p wsg-lib --example demo` | **Showcase**: one of each primitive, procedural textures, directional + point + spot lights, a shadow-casting light, and a live orbital camera (drag / wheel zoom / `R` reset / `1`-`3` presets). |
| `simple` | `cargo run -p wsg-lib --example simple` | Flat unlit quad (minimal declarative workflow, `AppBuilder` + auto scene). |
| `cube` | `cargo run -p wsg-lib --example cube` | Textured cube (procedural checker) lit by a directional + point + spot light. |
| `manual` | `cargo run -p wsg-lib --example manual` | Low-level workflow: `Context`, `Renderer`, `PipelineCache`, `Mesh` used directly (no `App` facade). |
| `spot_test` | `cargo run -p wsg-lib --example spot_test` | Spot-light isolation: only one spot is on (near-zero ambient), cube rotates on two axes so the oriented beam is clearly visible. |
| `shadow_test` | `cargo run -p wsg-lib --example shadow_test` | Shadow mapping: one directional light is the shadow caster (`set_shadow_caster(Some(0))`); a cube casts a PCF-softened shadow onto a thin ground slab. |
| Exemple | Effet démontré |
|---------|---------------|
| `demo` | Showcase complet (tous les effets combinés) |
| `bloom` | Post-process bloom (glow autour des zones brillantes) |
| `hdr` | HDR + Tone Mapping (ACES) + contrôle d'exposition |
| `emissive` | Matériaux émissifs (intensités croissantes 0 → 4.0) |
| `shadow` | Shadow mapping (ombre portée directionnelle) |
| `culling` | Culling GPU-driven (grille 20×20, objets hors frustum ignorés) |
| `manual` | Workflow bas niveau (Context + Renderer + PipelineCache) |
| `import` | Import de fichier OBJ (non graphique, stdout) |
## Conventions
---
- Examples are **self-contained**: no assets loaded from disk (procedural textures, hardcoded geometry).
- They use the declarative workflow (`AppBuilder` + `Scene`) except `manual`, which bypasses the `App` facade.
- When adding a new example: create a `.rs` file in this directory, document it here, and reference it in the root README if appropriate.
## `demo` — Showcase complet
Combine **tous** les effets : primitives LOD, textures procédurales, lumières
(directional + point + spot), ombres, HDR/ACES, exposition, émissif, bloom, culling.
```sh
cargo run -p wsg-lib --example demo
```
### Touches
| Touche | Action |
|--------|--------|
| Glisser (LMB) | Orbiter la caméra |
| Molette | Zoom |
| `R` | Reset caméra |
| `1` / `2` / `3` | Presets : face / côté / dessus |
| `+` / `-` | Exposition ×1.3 / ÷1.3 |
| `0` | Reset exposition |
---
## `bloom` — Post-process Bloom
Deux sphères émissives (orange intensité 2.0, bleue intensité 3.0) produisent un
halo visible. Le cube et le sol servent de référence (non-émissifs).
Le bloom est un pipeline 4 passes GPU : threshold → blur H → blur V → composite.
```sh
cargo run -p wsg-lib --example bloom
```
### Touches
| Touche | Action |
|--------|--------|
| Glisser (LMB) | Orbiter la caméra |
| Molette | Zoom |
| `R` | Reset caméra |
| `+` / `-` | **Bloom threshold** +0.1 / −0.1 |
| `[` / `]` | **Bloom intensity** +0.1 / −0.1 |
| `I` / `O` | **Bloom radius** +0.5 / −0.5 |
| `E` / `Q` | Exposition ×1.3 / ÷1.3 |
| `0` | Reset exposition |
### Ce qu'on voit
- **threshold bas** (0.0) : tout l'image "bloom" (effet très diffus).
- **threshold élevé** (2.0+) : seules les sphères émissives brillantes produisent du glow.
- **intensity 0.0** : pas de glow visible (même si le threshold extrait des pixels).
- **radius grand** (10+) : le glow s'étend sur une grande zone.
---
## `hdr` — HDR + Tone Mapping
Démontre le rendu HDR avec la courbe ACES Filmic. Trois objets :
- **Cube** : éclairage normal (aucun émissif) — référence LDR.
- **Sphère brillante** (émissif 3.0) : sans HDR, elle serait clampée à blanc.
Avec ACES, les highlights "roulent" doucement vers le blanc (rolloff).
- **Sphère sombre** (émissif 0.3) : reste sombre même à haute exposition.
```sh
cargo run -p wsg-lib --example hdr
```
### Touches
| Touche | Action |
|--------|--------|
| Glisser (LMB) | Orbiter la caméra |
| Molette | Zoom |
| `R` | Reset caméra |
| `E` | **Exposition ×1.3** (plus clair) |
| `Q` | **Exposition ÷1.3** (plus sombre) |
| `0` | Reset exposition à 1.0 |
### Ce qu'on voit
- À exposition 1.0 : la sphère brillante est blanche mais avec des détails (rolloff ACES).
- À exposition haute (E×E×E) : la scène s'éclaircit, la sphère brillante reste blanche
(saturée), mais le cube gagne en détail.
- À exposition basse (Q×Q) : tout s'assombrit, la sphère brillante devient orangée
(les valeurs HDR > 1.0 sont compressées).
> **Note** : le tone mapper est compilé dans le pipeline au build. Pour comparer
> ACES vs Reinhard, modifier `ToneMapper::Aces` → `ToneMapper::Reinhard` dans le source.
---
## `emissive` — Matériaux Émissifs
Cinq sphères alignées avec des intensités émissives croissantes :
| Sphere | Couleur | Intensité | Effet |
|--------|---------|-----------|-------|
| 1 | Gris | 0.0 | Aucune glow (référence) |
| 2 | Orange | 0.5 | Légère lueur |
| 3 | Jaune | 1.0 | Lueur visible |
| 4 | Vert | 2.0 | Glow HDR (au-delà de 1.0) |
| 5 | Bleu | 4.0 | Glow intense (saturation) |
Avec HDR, les intensités > 1.0 produisent un vrai "glow" (les valeurs dépassent
[0,1] en espace linéaire). Sans HDR, elles seraient clampées à blanc.
```sh
cargo run -p wsg-lib --example emissive
```
### Touches
| Touche | Action |
|--------|--------|
| Glisser (LMB) | Orbiter la caméra |
| Molette | Zoom |
| `R` | Reset caméra |
| `E` / `Q` | Exposition ×1.3 / ÷1.3 |
| `0` | Reset exposition |
| `C` | **Cycler le multiplicateur d'émissif** (1× → 2× → 0.5× → ...) |
### Ce qu'on voit
- La sphère 1 (intensité 0) est simplement éclairée par la lumière directionnelle.
- Les sphères 2-5 brillent de leur propre lumière, indépendamment de l'éclairage.
- `C` double ou réduit toutes les intensités en même temps (pour voir l'effet HDR).
---
## `shadow` — Shadow Mapping
Quatre objets (cube, sphère, cône, cylindre) sur un sol, éclairés par une lumière
directionnelle qui projette des ombres. La qualité des ombres est contrôlée par
`ShadowConfig` (taille de la shadow map, biais anti-acne).
```sh
cargo run -p wsg-lib --example shadow
```
### Touches
| Touche | Action |
|--------|--------|
| Glisser (LMB) | Orbiter la caméra |
| Molette | Zoom |
| `R` | Reset caméra |
| `1` | Vue de face |
| `2` | Vue de côté |
| `3` | **Vue de dessus** (voir la forme des ombres clairement) |
| `L` | Changer la direction de la lumière (3 presets) |
### Ce qu'on voit
- Le cube tourne lentement → son ombre bouge sur le sol.
- La sphère a une transition ombre/lumière douce (terminateur lisse).
- Le cône produit une ombre triangulaire distincte.
- En vue de dessus (`3`), on voit la forme exacte des ombres projetées.
- La taille de la shadow map (1024 par défaut) détermine la résolution :
modifier `SHADOW_MAP_SIZE` en haut du fichier pour tester 256 (pixelisé) ou 2048 (net).
---
## `culling` — GPU Frustum Culling
Une grille de **15×15 = 225 cubes** est placée sur un grand sol. Le culling
GPU-driven (compute shader) détermine quels cubes sont visibles dans le frustum
de la caméra et zéro leurs draw args indirects — **zéro coût CPU**.
```sh
cargo run -p wsg-lib --example culling
```
### Touches
| Touche | Action |
|--------|--------|
| Glisser (LMB) | Orbiter la caméra (regarder autour) |
| Molette | Zoom in/out |
| `R` | Reset (vue de dessus) |
| `1` | Vue de face (les cubes derrière sont culled) |
| `2` | Vue de côté |
| `3` | **Vue de dessus** (voir toute la grille) |
### Ce qu'on voit
- En vue de dessus (`3`) : toute la grille 20×20 est visible.
- Orbiter à 90° : les cubes derrière la caméra **ne sont pas dessinés** (culled).
- Zoomer très près : seuls les cubes proches du plan de near sont rendus.
- Les cubes tournent lentement (phases décalées) → le culling est dynamique
(un cube peut entrer/sortir du frustum au cours d'une frame).
> **Note** : le culling est activé via `AppBuilder::with_culling(true)`. Le modifier
> à `false` dans le source désactive le culling (tous les 400 cubes sont toujours
> dessinés, même hors écran).
---
## `manual` — Workflow bas niveau
Démontre l'API **sans** la façade `App` : utilisation directe de `Context`,
`Renderer`, `PipelineCache`, `Mesh`, `Material`. Rend un quad coloré (unlit).
Utile pour comprendre ce que la façade `App` encapsule.
```sh
cargo run -p wsg-lib --example manual
```
Pas de touches — rendu statique (quad unlit, 4 couleurs).
---
## `import` — Import de fichier OBJ
Exemple **non graphique** : parse un fichier `.obj` et affiche les statistiques
(nombre de sommets, normales, UVs, indices, bounding box) sur stdout.
```sh
# Avec un fichier :
cargo run -p wsg-lib --example import --features import-obj -- /path/to/model.obj
# Sans argument (triangle de démonstration) :
cargo run -p wsg-lib --example import --features import-obj
```
Pas de touches — s'exécute et quitte.