3.3 KiB
3.3 KiB
Bloom (Étape 23)
Le bloom est un post-process qui crée un effet de "glow" autour des zones brillantes de l'image. Les pixels dont la luminance dépasse un seuil sont extraits, floutés, puis ajoutés à l'image originale.
Prérequis : le bloom nécessite l'HDR (
AppBuilder::with_hdr). Sans HDR, les valeurs sont déjà clampées à [0,1] et il n'y a rien de "brillant" à extraire.
Activation
use wsg_lib::prelude::*;
let app = AppBuilder::new()
.with_hdr(ToneMapper::Aces) // requis
.with_bloom(BloomConfig {
threshold: 1.0, // seuil de luminance HDR
knee: 0.5, // largeur du soft-knee
intensity: 0.8, // intensité du glow
radius: 4.0, // rayon du blur (pixels, demi-rés)
..Default::default()
})
.build()
.await?;
BloomConfig
| Champ | Type | Défaut | Description |
|---|---|---|---|
threshold |
f32 |
1.0 |
Seuil de luminance (unités HDR linéaires). Seuls les pixels > seuil contribuent au bloom. |
knee |
f32 |
0.5 |
Largeur du soft-knee. Plus grand = transition plus douce. |
intensity |
f32 |
0.8 |
Multiplicateur appliqué au résultat flouté avant addition à l'HDR. |
radius |
f32 |
4.0 |
Rayon du blur en pixels (à la demi-résolution). Plus grand = glow plus étendu. |
Mise à jour runtime
// Dans le handler (fn update):
if app.bloom_enabled() {
app.set_bloom_config(BloomConfig {
intensity: new_intensity,
..app.bloom_config()
});
}
Les changements prennent effet au frame suivant (les uniforms sont ré-écrits chaque frame).
Pipeline (4 passes GPU)
Scene ──→ HDR (full res, Rgba16Float)
│
├──→ [1] Threshold (full → half res)
│ Soft-knee: smoothstep(knee, knee+1, lum)
│
├──→ [2] Blur H (half res)
│ 9-tap Gaussian séparable, direction = (1/w, 0)
│
├──→ [3] Blur V (half res)
│ 9-tap Gaussian séparable, direction = (0, 1/h)
│ (ping-pong: écrit dans la texture bright)
│
└──→ [4] Composite (full res)
output = HDR + bloom × intensity
(écrit dans une 3e texture full-res)
│
▼
Tone Mapping (lit le composite)
│
▼
Surface (sRGB)
Coût
- Sans bloom (défaut) : zéro overhead. Le TM lit directement la texture HDR.
- Avec bloom : 4 passes supplémentaires (1 full-res + 3 half-res) + 3 textures intermédiaires. Le coût est modéré car le blur est en demi-résolution.
Non-régression
with_bloom()sanswith_hdr()→ warning + no-op (le bloom est ignoré).- Sans
with_bloom()→ le TM lit la texture HDR directement (comportement Étape 20 inchangé).
Limitations (MVP)
- Un seul niveau de mip (pas de multi-mip "soft" bloom à la Unreal).
- Pas de directional bloom.
- Le blur est un Gaussian 9-taps (qualité suffisante pour un glow "soft").
- Pas de bloom séparé par couche (pas de "bloom mask" par matériau).