Files
wsg/lib/examples/README.md
T
Jérôme Bousquié 8ece89ccba dof
2026-09-25 13:43:59 +02:00

322 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Exemples WSG
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`).
## Lancer un exemple
```sh
cargo run -p wsg-lib --example <nom>
```
| 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 15×15, objets hors frustum ignorés) |
| `msaa` | MSAA 4× (anti-aliasing multi-échantillons, arêtes lisses) |
| `fog` | Brouillard de distance (3 modes : linéaire, exp, exp²) |
| `manual` | Workflow bas niveau (Context + Renderer + PipelineCache) |
| `import` | Import de fichier OBJ (non graphique, stdout) |
---
## `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).
---
## `msaa` — MSAA 4× (Anti-aliasing)
Démontre l'anti-aliasing multi-échantillons : les arêtes des objets (cube, sphère)
sont lisses au lieu d'être "en escalier". La scène contient un cube (arêtes nettes),
une sphère (silhouette courbe) et un petit cube près de la caméra (aliasing maximal).
```sh
cargo run -p wsg-lib --example msaa
```
### Touches
| Touche | Action |
|--------|--------|
| Glisser (LMB) | Orbiter la caméra |
| Molette | Zoom |
| `R` | Reset caméra |
| `M` | Afficher le nombre d'échantillons |
### Pour comparer avec/sans MSAA
Supprimer la ligne `.with_msaa(4)` dans le source et recompiler : la scène est
identique, seules les arêtes diffèrent (escaler vs lisse).
> **Note** : MSAA est un réglage de build-time (allocation de textures multi-échantillons).
> Il fonctionne indépendamment de HDR : avec HDR, la texture MSAA est `Rgba16Float`
> et résout dans la texture HDR avant bloom/TM.
---
## `fog` — Brouillard de distance
Démontre les 3 modes de brouillard : **linéaire**, **exponentiel**, **exponentiel²**.
La scène contient une rangée de cubes qui s'éloignent et des sphères dispersées sur
un grand plan au sol. Le brouillard fond les objets vers une couleur de fond,
créant l'illusion d'un monde infini.
```sh
cargo run -p wsg-lib --example fog --features "all-prims"
```
**Touches** : `1` = linéaire, `2` = exp, `3` = exp², `4` = désactivé, `R` = reset.
> Le brouillard est appliqué dans le shader fragment principal (après l'éclairage,
> avant le tone mapping). Il utilise la distance euclidienne du fragment à la caméra.
---
## `dof` — Depth of Field (bokeh cinématique)
Démontre le flou de profondeur de champ : un objet au centre reste net tandis que
le premier et arrière-plan se flouent selon leur distance au plan de mise au point.
Crée un effet d'attention naturelle (type cinématique).
La scène contient un cube de focus au centre, des sphères en premier plan (proches)
et des cubes en arrière-plan (loin), sur un plan au sol.
```sh
cargo run -p wsg-lib --example dof --features "all-prims"
```
**Touches** : `1` = cinématique, `2` = subtil, `3` = focus 2m, `4` = focus 10m, `5` = off, `R` = reset.
> DoF opère en HDR linéaire (après bloom, avant tone mapping). Deux passes :
> CoC (depth → rayon de flou par pixel) puis blur disque 12-taps à rayon variable.
---
## `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.