docs(renderer): Étape 9 depth buffer — bilan, README et resize planifié

- DRAFT.md : cases 9.1-9.4 cochées (terminées et vérifiées 2026-09-18),
  point d'étape validé, bilan de fin d'étape rédigé.
- README.md : Renderer::new prend désormais width/height (signature Étape 9).
- ROADMAP.md : décisions D1-D4 actées + resize avec recréation de la depth
  texture planifié en Phase 4.4 (acté D3, 2026-09-18).
This commit is contained in:
Jérôme Bousquié
2026-09-18 13:08:00 +02:00
parent fca5d728ad
commit dfa7403260
3 changed files with 131 additions and 5 deletions
+117 -4
View File
@@ -1,6 +1,119 @@
# DRAFT — Prochaine étape
# DRAFT — Étape 9 : Depth Buffer
> Document de travail de la prochaine étape (ROADMAP). Rempli au début de chaque étape
> et vidé à sa complétion. Source de vérité = code + README.md.
> 📅 **Rédigé le 2026-09-18.** Fonctionnel validé, plan à valider avant implémentation.
> Source de vérité = code + README.md. Ce document est vidé à la complétion de l'étape.
_Prêt pour la prochaine étape._
## Contexte (constat d'observation)
L'exemple `cube` en rotation montre que **la profondeur n'est pas calculée** : les faces
les plus lointaines ne sont pas masquées par les faces plus proches. Causes identifiées dans
le code (observation du 2026-09-18) :
- `lib/src/pipeline/pipeline_cache.rs` → `depth_stencil: None` à la création du pipeline (L233).
- `lib/src/core/renderer.rs` → les deux render passes (`render`, `render_scene`) ne posent
**aucun** `depth_stencil_attachment` ; seul un `color_attachments` est fourni (L194, L239).
- Aucune texture de profondeur n'est créée, donc aucun z-test n'est exécuté.
**Conclusion** : non implémenté (pas un bug). C'est un prérequis de correction du rendu avant
les textures (Phase 4.1), tel que décidé avec l'utilisateur le 2026-09-18.
## Objectif
Activer le test de profondeur (z-buffer) sur tous les chemins de rendu (`render` ET `render_scene`)
pour que les faces cachées soient correctement masquées.
## Décisions (validées le 2026-09-18)
- **[x] D1 (format)** — *(validée 2026-09-18)* : texture de profondeur `TextureFormat::Depth32Float`,
valeur de clear `1.0` (portée maximale), `depth_compare: Less`, `depth_write_enabled: true`.
- **[x] D2 (portée)** — *(validée 2026-09-18)* : le depth buffer est posé sur **les deux** render
passes (bas niveau `render` et haut niveau `render_scene`), pas seulement `render_scene`, pour
garder la cohérence du flux 2D.
- **[x] D3 (résolution)** — *(validée 2026-09-18)* : la texture de profondeur est allouée à la taille
de la surface initiale. **Le resize est planifié comme chantier dédié** dans `docs/ROADMAP.md`
(Phase 4.4, avec recréation de la depth texture en même temps que la reconfiguration de la surface),
hors périmètre de l'Étape 9. On créera un helper `create_depth_texture` isolé pour rendre ce
recreate trivial plus tard.
- **[x] D4 (échantillonnage)** — *(validée 2026-09-18, YAGNI)* : aucune texture de profondeur n'est
échantillonnée pour l'instant (pas de shadow mapping ni de post-processing) — on n'a donc pas
besoin de l'exposer dans un bind group. Simple render target + state pipeline suffisent ; le bind
group sera ajouté quand le shadow mapping arrivera.
## Plan d'implémentation
### 9.1 — Créer la texture de profondeur dans `Renderer` *(terminée et vérifiée le 2026-09-18)*
- [x] Ajouter un champ `depth_view: wgpu::TextureView` au `Renderer` (avec helper pour allouer
`depth_texture` + `depth_view` à partir de `device` et de la taille surface).
- [x] Taille : `width`/`height` passés à `Renderer::new` (aujourd'hui il ne reçoit que `format`).
Portée : avantage à `create_depth_texture(device, width, height, format)`.
- [x] `TextureDescriptor` : `size: Extent3d { width, height, depth_or_array_layers: 1 }`,
`mip_level_count: 1`, `sample_count: 1`, `dimension: D2`,
`format: wgpu::TextureFormat::Depth32Float`,
`usage: RENDER_ATTACHMENT`, `label: Some("depth texture")`.
### 9.2 — Attacher le depth au render pass *(terminée et vérifiée le 2026-09-18)*
- [x] Dans `render_scene` (renderer.rs) : ajouter `depth_stencil_attachment: Some(...)` au
`RenderPassDescriptor`, avec `depth_ops: Operations { load: Clear(1.0), store: Store }`.
- [x] Même ajout dans `render` (renderer.rs) pour la cohérence du chemin bas niveau.
### 9.3 — Activer le depth-stencil state dans le pipeline *(terminée et vérifiée le 2026-09-18)*
- [x] Dans `pipeline_cache.rs` (L233) : remplacer `depth_stencil: None` par
`Some(DepthStencilState { format: Depth32Float, depth_write_enabled: Some(true),
depth_compare: Some(CompareFunction::Less), stencil: StencilState::default(),
bias: DepthBiasState::default() })` — note : en wgpu 30, `depth_write_enabled` et
`depth_compare` sont des `Option` (le DRAFT initial les donnait nus).
- [x] Le format du depth doit matcher celui de la texture (D1 : `Depth32Float`) — garanti par la
constante partagée `DEPTH_FORMAT` (pipeline_cache.rs), réexportée via `pipeline::mod`.
### 9.4 — Vérification *(terminée et vérifiée le 2026-09-18)*
- [x] `cargo fmt --all` (aucun diff attendu), `cargo check --workspace` (zéro warning),
`cargo test --workspace` (vert : 3 tests), `cargo doc` (pas de `missing_docs`).
- [x] Lancer l'exemple `cube` (`cargo run -p wsg-lib --example cube`) : tourne sans erreur backend
(le z-buffer est accepté par wgpu, aucun format mismatch) — faces arrière masquées.
- [x] Lancer `simple` (rendu plat via `render_scene`) : pas de régression, tourne sans erreur GPU.
## Point d'étape
- [x] Valider D1–D4 avant implémentation. *(fait — 2026-09-18 : D1 Depth32Float, D2 les deux passes,
D3 resize planifié dans RoADMAP Phase 4.4, D4 YAGNI)*
- [x] Caser 9.1–9.4, validation verte, exemples OK. *(fait — 2026-09-18)*
- [x] Deux commits séparés : `refactor(...)` (9.1–9.3) puis `docs(...)` (9.4) + README/DRAFT.
*(fait — refactor fca5d72 puis docs)*
- [x] Rédiger le bilan et ouvrir la suite (textures/matériaux Phase 4.1).
---
## Bilan de l'Étape 9 — Depth Buffer (terminée le 2026-09-18)
La profondeur est maintenant calculée sur **tous** les chemins de rendu :
- **1 texture de profondeur partagée** (`Depth32Float`, D1), allouée par le `Renderer` à la taille
de la surface initiale, gardée vivante par le champ `_depth_texture` (rétention) et vue via
`depth_view`.
- **Les deux render passes** (`render` bas niveau et `render_scene` haut niveau) posent un
`depth_stencil_attachment` identique (clear `1.0` / store), ce qui masque les faces arrière du
cube en rotation (D2).
- **Toutes les pipelines** déclarent un `DepthStencilState` cohérent (write `true`, compare `Less`)
via la constante partagée `DEPTH_FORMAT` — impossible d'avoir un format pipeline ≠ texture.
### Décisions appliquées
- **D1** : `Depth32Float`, clear `1.0`, compare `Less`, write `true`. ✓
- **D2** : profondeur posée sur `render` ET `render_scene`. ✓
- **D3** : texture à la taille initiale ; le resize (recréation de la depth texture à chaque
changement de taille, couplée à la reconfiguration surface) est planifié en **ROADMAP Phase 4.4**.
Le helper `create_depth_texture` isolé rend ce recreate trivial. ✓
- **D4** (YAGNI) : pas de bind group présentant la profondeur ; simple render target + state
pipeline. Le bind group attendra le shadow mapping. ✓
### API modifiée (breaking)
- `Renderer::new(context, format)` → `Renderer::new(context, format, width, height)` —
les appelants (`app.rs`, `manual.rs`, `README.md`) ont été mis à jour en conséquence.
### Commits de l'étape
- `fca5d72` refactor(renderer): activate depth buffer on all render paths (9.1–9.3)
- *(docs — 9.4 : DRAFT coché + bilan, README mis à jour)*
### Suite logique
Ouvrir la Phase 4.1 (Textures / matériaux) — le z-buffer était le prérequis de lisibilité : les
faces arrière étant désormais masquées, un cube texturé sera correctement rendu.
_Fin de l'Étape 9._