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

134 lines
3.9 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.
# Brouillard de distance (Fog)
## Principe
Le brouillard de distance fond les objets vers une couleur prédéfinie en fonction
de leur distance à la caméra. C'est l'outil standard pour :
- **Masquer le bord du monde rendu** — illusion d'un monde infini (Skyrim, GTA, Minecraft)
- **Donner de la profondeur** — effet atmosphérique naturel
- **Camoufler les transitions** — chargement de tuiles, LOD pops
## Activation
```rust
use wsg_lib::prelude::*;
let app = AppBuilder::new()
.with_fog(FogConfig::exponential2([0.7, 0.75, 0.85], 0.06))
.build()
.await?;
```
Sans `.with_fog()`, le brouillard est désactivé — **zéro coût GPU** (la branche
shader est jamais prise).
## Modes
| Mode | Formule | Usage |
|------|---------|-------|
| `Linear` | `saturate((far - d) / (far - near))` | Cutoff net entre deux distances |
| `Exponential` | `exp(-density × d)` | Brouillard naturel (forêt, lac) |
| `Exponential2` | `exp(-density² × d²)` | Départ progressif, cutoff net — **idéal pour masquer** |
### Constructeurs
```rust
// Linéaire : fondu entre near et far
FogConfig::linear([0.7, 0.8, 0.9], 5.0, 50.0)
// Exponentiel : fondu naturel
FogConfig::exponential([0.6, 0.7, 0.8], 0.03)
// Exponentiel² : masquage de bord de monde
FogConfig::exponential2([0.7, 0.75, 0.85], 0.08)
```
## Paramètres
| Champ | Type | Description |
|-------|------|-------------|
| `mode` | `FogMode` | Linéaire / Exponentiel / Exponential2 |
| `color` | `[f32; 3]` | Couleur du brouillard (RGB, espace linéaire) |
| `near` | `f32` | Distance début (mode linéaire uniquement) |
| `far` | `f32` | Distance fin, brouillard complet (mode linéaire) |
| `density` | `f32` | Densité (modes exp / exp²). Typique : 0.01–0.3 |
### Choisir la couleur
La couleur du brouillard **doit correspondre à la couleur du ciel/clear color**
pour un effet "monde infini" seamless. Avec HDR + ACES, utiliser des valeurs
linéaires cohérentes avec le tone mapping.
### Choisir la densité (exp²)
Pour masquer le bord du monde à une distance `D` :
```
density ≈ 2.0 / D
```
Exemples :
- Monde visible jusqu'à 25 unités → `density = 0.08`
- Monde visible jusqu'à 50 unités → `density = 0.04`
- Monde visible jusqu'à 100 unités → `density = 0.02`
## Changement à l'exécution
```rust
// Dans update() :
if key_pressed(KeyCode::Digit1) {
app.renderer_mut().set_fog(Some(FogConfig::linear([0.7, 0.8, 0.9], 5.0, 30.0)));
}
if key_pressed(KeyCode::Digit4) {
app.renderer_mut().set_fog(None); // désactiver
}
```
Le changement prend effet au frame suivant.
## Pipeline
```text
Main pass (shader fragment)
↓
Lighting → final_rgb
↓
FOG: mix(final_rgb, fog_color, 1 - fog_factor) ← ici
↓
→ HDR texture / swapchain
↓
(Bloom) → Tone Mapping → surface
```
Le brouillard s'applique **avant** le tone mapping : les valeurs HDR restent
non clampées, et le TM applique la courbe ACES/Reinhard au résultat déjà
brouillé. Résultat : le brouillard est perceptuellement cohérent.
## Compatibilité
| Avec | OK ? | Note |
|------|------|------|
| HDR + TM | ✅ | Fog avant TM (recommandé) |
| Bloom | ✅ | Le bloom extrait les zones brillantes du résultat post-fog |
| MSAA | ✅ | Indépendant (rasterizer vs fragment shader) |
| Culling GPU | ✅ | Indépendant (culling décide quoi dessiner, fog décide la couleur) |
| Shadows | ✅ | L'ombre est calculée avant le fog |
## Limitations (v1)
- **Scene-level uniquement** : un seul brouillard pour toute la scène.
Un brouillard par matériau nécessiterait un paramètre additionnel dans le
bind group par objet.
- **Distance euclidienne** : pas de brouillard volumétrique ni directionnel.
- **Couleur fixe** : pas de gradient de couleur avec la distance.
## Exemple
Voir `examples/fog.rs` : 15 cubes en rangée + 5 sphères sur un plan 80×80,
avec commutation runtime entre les 3 modes.
```sh
cargo run -p wsg-lib --example fog --features "all-prims"
```