From 9ad47e879003d5956c003cbbd4b8343475faeb5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Bousqui=C3=A9?= Date: Fri, 18 Sep 2026 10:22:43 +0200 Subject: [PATCH] =?UTF-8?q?docs(=C3=A9tape8):=20valider=20et=20documenter?= =?UTF-8?q?=20le=20refactor=20stockage=20CPU=20Arc=20(8.6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DRAFT.md : cases 8.1-8.6 cochées, état 'terminée et vérifiée 2026-09-18', bilan final. - README.md : workflow manuel et déclaratif (extraits Mesh::new -> Geometry/from_geometry), note API create_mesh(Geometry), section architecture + table quick reference, roadmap +1 (CPU storage). - ROADMAP.md (1.2) : colors + refactor Mesh/Scene cochés 'fait', déviation D3 'implémenté'. - PLAN.md : statut réel à jour 2026-09-18 (Étape 8 effectuée). - resources/README.md : Mesh::new() -> from_geometry() + rétention CPU. --- README.md | 43 +++++++++++++++++--------- docs/DRAFT.md | 61 +++++++++++++++++++++++++------------ docs/PLAN.md | 8 +++-- docs/ROADMAP.md | 25 +++++++++------ lib/src/resources/README.md | 2 +- 5 files changed, 92 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 21c3239..bed4544 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ WSG is a Rust library that wraps [wgpu](https://github.com/gfx-rs/wgpu) and [winit](https://crates.io/crates/winit) for simple GPU drawing. It groups the five core wgpu objects (Instance, Surface, Adapter, Device, Queue) behind a single `Context`, adds small building blocks (`Mesh`, `Material`, `PipelineCache`, `Frame`), and exposes the low-level primitives for advanced users. -> **Status: unstable development version.** The manual workflow below is fully working, the high-level "declarative" workflow (automatic `App` scene rendering) works for flat/NDC drawing, and the **3D MVP is reached** : the `cube` example (Étape 5) renders a rotating, Phong-lit cube through `App::render_scene`. The GPU-driven two-pass pipeline described in the architecture docs is **not implemented yet** — see [Status](#status) and [Roadmap](#roadmap). +> **Status: unstable development version.** The manual workflow below is fully working, the high-level "declarative" workflow (automatic `App` scene rendering) works for flat/NDC drawing, and the **3D MVP is reached** : the `cube` example (Étape 5) renders a rotating, Phong-lit cube through `App::render_scene`. Since Étape 8, meshes are declared from a CPU `Geometry` (retained as `Arc` on the Mesh) instead of raw vertex arrays. The GPU-driven two-pass pipeline described in the architecture docs is **not implemented yet** — see [Status](#status) and [Roadmap](#roadmap). ## Status @@ -28,7 +28,7 @@ use winit::event_loop::EventLoop; use winit::window::WindowBuilder; use wsg_lib::core::{Context, Frame, Renderer}; use wsg_lib::pipeline::PipelineCache; -use wsg_lib::resources::{Material, Mesh, Vertex}; +use wsg_lib::resources::{Geometry, Material, Mesh}; use wsg_lib::utils; fn main() { @@ -45,16 +45,23 @@ fn main() { let mut cache = PipelineCache::new(Arc::new(context.device.clone())); cache.register_shader("standard", utils::STANDARD_SHADER_PATH).unwrap(); - // Material + mesh + // Material + mesh (Étape 8 : le mesh est construit depuis une `Geometry` — positions, + // attributs optionnels en builder, défauts blancs via `to_vertices`). let material = Material::new(renderer.format(), "standard", &mut cache); - let vertices: [Vertex; 4] = [ - Vertex { position: [-0.5, 0.5, 0.0], normal: [0.0, 0.0, 1.0], uv: [0.0, 0.0], color: [1.0, 0.0, 0.0, 1.0] }, - Vertex { position: [ 0.5, 0.5, 0.0], normal: [0.0, 0.0, 1.0], uv: [1.0, 0.0], color: [0.0, 1.0, 0.0, 1.0] }, - Vertex { position: [ 0.5, -0.5, 0.0], normal: [0.0, 0.0, 1.0], uv: [1.0, 1.0], color: [0.0, 0.0, 1.0, 1.0] }, - Vertex { position: [-0.5, -0.5, 0.0], normal: [0.0, 0.0, 1.0], uv: [0.0, 1.0], color: [1.0, 1.0, 0.0, 1.0] }, - ]; - let indices: [u16; 6] = [0, 1, 2, 0, 2, 3]; - let mesh = Mesh::new(renderer.device(), &vertices, Some(&indices)); + let geometry = Geometry::new(vec![ + [-0.5, 0.5, 0.0], // Haut-Gauche + [ 0.5, 0.5, 0.0], // Haut-Droite + [ 0.5, -0.5, 0.0], // Bas-Droite + [-0.5, -0.5, 0.0], // Bas-Gauche + ]) + .with_colors(vec![ + [1.0, 0.0, 0.0, 1.0], // Rouge + [0.0, 1.0, 0.0, 1.0], // Vert + [0.0, 0.0, 1.0, 1.0], // Bleu + [1.0, 1.0, 0.0, 1.0], // Jaune + ]) + .with_indices(vec![0, 1, 2, 0, 2, 3]); + let mesh = Mesh::from_geometry(renderer.device(), Arc::new(geometry), None); // Render loop event_loop.run(|event, elwt| { @@ -96,10 +103,13 @@ async fn main() -> Result<(), wsg_lib::utils::WsgError> { // Register your scene once (string IDs), then App renders it automatically each frame. // Since Étape 7 the Scene owns the pipeline cache: build materials/meshes through it and // link the material to the mesh (no material_id on the entity anymore). + // Since Étape 8 meshes are declared from a `Geometry` (positions + optional attributes). // app.renderer_mut().set_unlit(true); // select flat 2D rendering (optional) // app.scene.register_shader("standard", wsg_lib::utils::STANDARD_SHADER_PATH)?; // app.scene.add_material_shader("mat", "standard")?; // build via the Scene's cache - // app.scene.create_mesh("quad", &vertices, Some(&indices), Some("mat"))?; // mesh links its Material + // let geometry = wsg_lib::resources::Geometry::new(vec![[-0.5,0.5,0.0],[0.5,0.5,0.0]]) + // .with_colors(vec![[1.0,0.0,0.0,1.0],[0.0,1.0,0.0,1.0]]); + // app.scene.create_mesh("quad", geometry, Some("mat"))?; // mesh links its Material // app.scene.add_entity("my_quad", "quad")?; app.run(MyGame) @@ -108,13 +118,14 @@ async fn main() -> Result<(), wsg_lib::utils::WsgError> { > API note: `Scene::register_shader` / `add_material_shader` / `create_mesh` / `add_entity` and > `PipelineCache::register_shader` currently return `Result<_, String>` — typed error unification -> is on the roadmap. +> is on the roadmap. Since Étape 8, `Scene::create_mesh(id, geometry, material)` takes a CPU +> `Geometry` (source of truth, retained on the Mesh) instead of raw `&[Vertex]`. ## Architecture overview - **Manager layer (`Context`)** — owns the GPU hardware lifecycle (Instance → Surface → Adapter → Device → Queue). Created once at startup; `configure()` sets up the swapchain, `Frame` wraps each frame's surface texture + view. - **Executor layer (`Renderer`)** — binds a `Material` pipeline + `Mesh` buffers into a RenderPass and submits the commands. Rendering a whole `Scene` (`render_scene`) batches all entities into **one encoder + one submit per frame**; the low-level `render` still allocates one per object. -- **Supporting pieces** — `PipelineCache` (shader → compiled RenderPipeline, `Arc`-shared), `Material`, `Mesh`/`Vertex`, `Scene` (string-ID registry), `Camera`/`Transform` (active camera wired to the frame uniforms, Étape 4.3). +- **Supporting pieces** — `PipelineCache` (shader → compiled RenderPipeline, `Arc`-shared), `Material`, `Geometry`/`Mesh`/`Vertex`, `Scene` (string-ID registry), `Camera`/`Transform` (active camera wired to the frame uniforms, Étape 4.3). `Geometry` is the CPU source of truth (positions/normals/UVs/colors), `Mesh` uploads it to GPU buffers and retains the `Arc`, `Vertex` is the interleaved upload contract (Étape 8). The planned target architecture — a GPU-driven two-pass pipeline (Compute Pass: world matrices + frustum culling → Indirect Draw Buffer, then a single `draw_indexed_indirect` per frame) — is specified in [docs/tech/ARCHI_APP.md](docs/tech/ARCHI_APP.md) and [docs/tech/ARCHI_CPU_GPU.md](docs/tech/ARCHI_CPU_GPU.md) but is **not implemented yet**. @@ -129,7 +140,8 @@ The planned target architecture — a GPU-driven two-pass pipeline (Compute Pass | Renderer | Struct | Binds Material + Mesh into a RenderPass, submits | ✅ (`render_scene` batches one pass/frame) | | PipelineCache | Struct | Shader → compiled RenderPipeline cache | ✅ | | Material | Struct | Shader ID → RenderPipeline | ✅ | -| Mesh / Vertex | Struct | GPU geometry container / CPU-side vertex tuple | ✅ | +| Geometry | Struct | CPU-side scattered vertex data (positions/normals/UVs/colors/indices), source of truth | ✅ (Étape 8 — retained `Arc` on Mesh) | +| Mesh / Vertex | Struct | GPU geometry container / CPU-side interleaved upload tuple | ✅ | | Frame | Struct | Per-frame RAII wrapper (surface texture + view) | ✅ | | Camera / Transform | Struct | Camera & transform math | ✅ Active camera + transform wired to per-frame uniforms (Étape 4.3) | @@ -170,3 +182,4 @@ The architecture docs live in `docs/tech/` and are written in **French**. Each d 4. ✅ **Real 3D pipeline (MVP atteint)** — MVP uniforms + camera support in the vertex shader. *(Engine plumbing done 2026-09-16 ; Étape 5, 2026-09-17 : `standard` branché sur l'exemple `cube` — un cube unitaire éclairé (Phong) qui tourne, rendu automatiquement par `App::render_scene`. Retrait de `basic` : le 2D plat = variante unlit de `standard` via `Renderer::set_unlit`.)* 5. **Typed resource handles** — keep String IDs for the MVP (current design, source of truth in `Scene`); slotmap-based generational handles (`ARCHI_ARENES.md`) are deferred to a later performance pass. 6. **Error unification** — replace `Result<_, String>` in `Scene`/`PipelineCache` with typed errors. +7. ✅ **CPU geometry storage (Étape 8)** — `Mesh` retains a shared `Arc` (CPU source of truth with colors) alongside its GPU buffers; meshes are declared from a `Geometry` via `Mesh::from_geometry`/`Scene::create_mesh(id, geometry, material)` instead of raw `&[Vertex]` arrays. (Done 2026-09-18; `transform` stays on `Entity` — deviation D3.) diff --git a/docs/DRAFT.md b/docs/DRAFT.md index 7f4dc36..943c4ef 100644 --- a/docs/DRAFT.md +++ b/docs/DRAFT.md @@ -4,8 +4,8 @@ > **Son contenu est effacé au début de chaque nouvelle étape.** La source de vérité de l'état est > le code + README.md ; les autres docs `docs/*` restent stables. -> **État.** Étape 8 en préparation — refactor du stockage CPU des données géométriques : -> `Mesh` contient `geometry: Arc`. Étape 7 terminée et vérifiée le 2026-09-17. +> **État.** Étape 8 **terminée et vérifiée le 2026-09-18** : `Mesh.geometry: Arc` + buffers +> dérivés, API `create_mesh` basée `Geometry`, exemples réécrits, validation verte, docs à jour. --- @@ -54,7 +54,7 @@ Valeurs apportées : ## Étape 8.1 — Étendre `Geometry` (couleur + validation) — **proposition validée 2026-09-18** -- [ ] Dans `lib/src/math/geometry.rs` : +- [x] Dans `lib/src/math/geometry.rs` : - [ ] ajouter `colors: Option>` en champ optionnel (parallèle à `normals`/`uvs`). - [ ] documenter les invariants : `positions` obligatoire ; `normals`, `uvs`, `colors`, `indices` optionnels mais doivent avoir la même longueur que `positions` quand présents. @@ -67,7 +67,7 @@ Valeurs apportées : ## Étape 8.2 — Convertisseur `Geometry` → `Vec` -- [ ] Dans `lib/src/math/geometry.rs` (ou un petit trait dédié), implémenter : +- [x] Dans `lib/src/math/geometry.rs` (ou un petit trait dédié), implémenter : - [ ] `Geometry::to_vertices() -> Vec` qui zip `positions`/`normals`/`uvs`/`colors` avec des valeurs par défaut : normale `[0,0,1]`, uv `[0,0]`, couleur blanche `[1,1,1,1]`. - [ ] documenter clairement ces défauts (i.e. une géométrie sans normales via Phong sera plate). @@ -75,7 +75,7 @@ Valeurs apportées : ## Étape 8.3 — `Mesh` contient `Arc` et construit ses buffers -- [ ] Dans `lib/src/resources/mesh.rs` : +- [x] Dans `lib/src/resources/mesh.rs` : - [ ] ajouter le champ `geometry: Arc`. - [ ] remplacer/ajouter `Mesh::from_geometry(device: &wgpu::Device, geometry: Arc, material: Option>) -> Mesh` : @@ -90,7 +90,7 @@ Valeurs apportées : ## Étape 8.4 — Adapter `Scene` / l'API déclarative -- [ ] Dans `lib/src/scene/scene.rs` : +- [x] Dans `lib/src/scene/scene.rs` : - [ ] changer `create_mesh(id, vertices: &[Vertex], indices, material)` → `create_mesh(id, geometry: Geometry, material: Option<&str>) -> Result<...>` : - [ ] il construit `Arc`, appelle `Mesh::from_geometry(self.device(), arc, mat)`. @@ -100,38 +100,61 @@ Valeurs apportées : ## Étape 8.5 — Réécrire les exemples (non contraignants) sur `Geometry` -- [ ] `lib/examples/cube.rs` : +- [x] `lib/examples/cube.rs` : - [ ] remplacer `cube_vertices() -> Vec` / `cube_indices()` par un builder de `Geometry` (ou `Geometry::new(...).with_normals(...).with_indices(...)`) ; couleur blanche par défaut → vérifier le rendu Phong inchangé. - [ ] appeler `scene.create_mesh("cube_mesh", geometry, Some("cube_material"))`. -- [ ] `lib/examples/simple.rs` : +- [x] `lib/examples/simple.rs` : - [ ] construire une `Geometry` (positions ± couleurs par sommet pour le quad unlit) ; - [ ] `scene.create_mesh("quad", geometry, None)` (matériau par défaut). -- [ ] `lib/examples/manual.rs` (exemple bas-niveau, utilise `Mesh::new(renderer.device(), +- [x] `lib/examples/manual.rs` (exemple bas-niveau, utilise `Mesh::new(renderer.device(), &vertices, ...)`) : - [ ] réécrire sur `Mesh::from_geometry(device, Arc, None)`. -- [ ] mettre à jour les en-têtes / commentaires des exemples (références à `Vertex` en public). +- [x] mettre à jour les en-têtes / commentaires des exemples (références à `Vertex` en public). ## Étape 8.6 — Validation -- [ ] `cargo fmt --all` (aucun diff résiduel). -- [ ] `cargo check --workspace` puis `cargo build --workspace` **sans warning** (veiller à la +- [x] `cargo fmt --all` (aucun diff résiduel). +- [x] `cargo check --workspace` puis `cargo build --workspace` **sans warning** (veiller à la régularité des tableaux dans les exemples). -- [ ] `cargo test --workspace` (zéro test à ce stade, mais compilation clean). -- [ ] `cargo doc --no-deps` **sans warning `missing_docs`** (la crate est en `#![warn(missing_docs)]`). -- [ ] Lancer les 3 exemples (simple, cube, manual) et constater l'absence de panic / rendu visé. -- [ ] Mettre à jour `README.md` (extraits de code `Mesh::new` → `Geometry`, section architecture) +- [x] `cargo test --workspace` (zéro test à ce stade, mais compilation clean). +- [x] `cargo doc --no-deps` **sans warning `missing_docs`** (la crate est en `#![warn(missing_docs)]`). +- [x] Lancer les 3 exemples (simple, cube, manual) et constater l'absence de panic / rendu visé. +- [x] Mettre à jour `README.md` (extraits de code `Mesh::new` → `Geometry`, section architecture) et les statuts `docs/PLAN.md` + `docs/ROADMAP.md` (cocher le refactor 1.2 « stockage CPU » ; laisser `transform` documenté comme déviation en D3). ## Point d'étape -- [ ] Caser le refactor : `Mesh.geometry: Arc` + buffers dérivés, API `create_mesh` +- [x] Caser le refactor : `Mesh.geometry: Arc` + buffers dérivés, API `create_mesh` basée `Geometry`, exemples réécrits, validation verte, docs à jour. -- [ ] Deux commits séparés comme d'habitude : un `refactor(...)` (8.1–8.5) puis un `docs(...)` +- [x] Deux commits séparés comme d'habitude : un `refactor(...)` (8.1–8.5) puis un `docs(...)` (8.6). Rédiger un court bilan et ouvrir la question du prochain chantier. +## Bilan (2026-09-18) + +L'Étape 8 est **terminée et vérifiée** : +- `Geometry` (math) : champ `colors`, constructeur `Geometry::new(positions)` + builder + fluent (`.with_normals/.with_uvs/.with_colors/.with_indices`), `validate()` + `GeometryError`, + `indices()` et `to_vertices()`/`try_into_vertices()` (zip positions/normals/uvs/colors avec défauts + normale `[0,0,1]`, uv `[0,0]`, blanc opaque). +- `Mesh` (resources) : retient `geometry: Arc` (CPU, D5) + buffers GPU pré-uploadés ; + constructeur **unique** `Mesh::from_geometry(device, Arc, Option>)` + (D4) — `Mesh::new`/`with_material` (`&[Vertex]`) supprimés ; accesseurs `geometry()`/`material()`/`set_material()`. +- `Scene` : `create_mesh(id, Geometry, Option<&str>)` (D4) ; `Geometry` exposé via `math` (D2) + et ré-exporté en convenance depuis `resources`. +- Exemples cube/simple/manual réécrits sur `Geometry` (8.5). `simple` passe par `None` pour + vérifier le matériau par défaut (`Scene::default_material`). +- Validation : `cargo fmt` (aucun diff), `build`/`check` sans warning, `test` vert (1 unitaire + shader + 1 doc-test `Geometry::new`), `doc` sans `missing_docs`, 3 exemples lancés (rendu sans panic). +- Commits : `refactor(...)` (8.1–8.5) + `docs(...)` (8.6). + +**Prochain chantier possible** : la suite du ROADMAP — gestion des matériaux/textures (Phase 2/4, +ex. `Texture` + `uniform` diffuse), ou remonter vers les **handles typés** (Phase 2/5) / pipeline +**GPU-driven** (Phase 3) avec la bounding box dans `Geometry` (le champ `colors` et la rétention CPU +`Arc` posent déjà la base du culling). + --- -_Fin du DRAFT Étape 8 — à valider avant implémentation._ +_Fin du DRAFT Étape 8 — implémentée et vérifiée le 2026-09-18._ diff --git a/docs/PLAN.md b/docs/PLAN.md index 487963c..12829de 100644 --- a/docs/PLAN.md +++ b/docs/PLAN.md @@ -11,7 +11,7 @@ generated: { by: human:jerome, at: 2026-07-31T00:00:00Z } Ce plan définit les étapes prioritaires pour finaliser l'architecture actuelle. L'objectif est de rendre l'API intuitive pour l'utilisateur standard tout en conservant la puissance de contrôle pour l'utilisateur avancé. -> **Statut réel (à jour au 2026-09-17).** Ce plan couvre la phase de *consolidation* passée ; la source +> **Statut réel (à jour au 2026-09-18).** Ce plan couvre la phase de *consolidation* passée ; la source > de vérité sur l'état actuel est **README.md** et le code. Depuis la révision du 2026-09-14, l'étape > **« Scene auto-render »** a été réalisée : le rendu de la `Scene` est **automatisé** en une seule > passe groupée via `App::render_scene(frame.view())` (appelée par défaut dans `AppHandler::render`), @@ -21,7 +21,11 @@ Ce plan définit les étapes prioritaires pour finaliser l'architecture actuelle > le buffer frame chaque frame, matrices monde par entité. **Étape 5 (2026-09-17) : MVP 3D atteint** — > l'exemple `cube` rend un cube unitaire éclairé (Phong) en rotation via `App::render_scene` ; le > shader `basic` est supprimé, le 2D plat devient la **variante unlit** de `standard` -> (`Renderer::set_unlit` / `app.renderer_mut().set_unlit(true)`). +> (`Renderer::set_unlit` / `app.renderer_mut().set_unlit(true)`). L'**Étape 7 (2026-09-17)** a rattaché +> le `PipelineCache` à la `Scene` et fait référencer son `Material` par chaque `Mesh`. L'**Étape 8 +> (2026-09-18)** a donné à `Mesh` une source de vérité **CPU partagée** (`geometry: Arc`) : +> `Scene::create_mesh(id, Geometry, material)` déclare les meshes depuis une `Geometry` (avec couleurs), +> `Mesh::from_geometry` dérive ses buffers GPU, et les exemples cube/simple/manual utilisent `Geometry`. ## Phase 1 : Finalisation et Nettoyage de l'Existant (Priorité Absolue) diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 5eb3146..c8d08fc 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -53,24 +53,29 @@ generated: { by: human:jerome, at: 2026-07-31T00:00:00Z } - [x] `positions: Vec<[f32; 3]>` (obligatoire) - [x] `indices: Option>` (optionnel) - [x] `normals: Option>` (pour Phong) — plus `uvs: Option>` - - [ ] `colors: Option>` — **décidé en DRAFT Étape 8 (D1)** : le shader lit la couleur - unlit, il faut la porter dans `Geometry` ; conversion `Geometry -> Vec` pour l'upload. -- [ ] Refactorer `Mesh` pour contenir : - - [ ] `geometry: Arc` - - [ ] `vertex_buffer: wgpu::Buffer` - - [ ] `index_buffer: Option` + - [x] `colors: Option>` — **fait (Étape 8, 8.1, 2026-09-18)** : décidé en DRAFT Étape 8 (D1) ; + le shader lit la couleur unlit, elle est donc portée dans `Geometry`. Conversion + `Geometry -> Vec` via `Geometry::to_vertices()` (D6) pour l'upload. +- [x] Refactorer `Mesh` pour contenir — **fait (Étape 8, 8.3, 2026-09-18)** : + - [x] `geometry: Arc` (rétention CPU, D5) + accesseur `geometry()` + - [x] `vertex_buffer: wgpu::Buffer` + - [x] `index_buffer: Option` + - Construction via `Mesh::from_geometry(device, Arc, material)` (D4) ; les anciennes + voies `Mesh::new`/`with_material` (`&[Vertex]`) sont supprimées. + - `Scene::create_mesh(id, Geometry, Option<&str>)` (8.4) ; exemples cube/simple/manual réécrits + sur `Geometry` (8.5). - [x] Ajouter un mesh de test (cube unitaire) en exemple — **fait** (helper `cube_geometry` dans l'exemple `cube`, Étape 5, 2026-09-17) -> **Note (2026-09-17, DRAFT Étape 7)** : le refactor « Mesh contient `Arc` » ci-dessus reste -> **reporté** (il porte sur le *stockage CPU* des données géométriques). En revanche le volet *matériau* -> de `Mesh` a été fait en Étape 7 : `Mesh.material: Option>` (cf. PLAN Phase 2, gestion des -> matériaux), indépendant de la structure `Geometry`. +> **Note (2026-09-17, DRAFT Étape 7)** : le volet *matériau* de `Mesh` a été fait en Étape 7 : +> `Mesh.material: Option>` (cf. PLAN Phase 2, gestion des matériaux), indépendant de +> la structure `Geometry`. > > **Décision **D3** (2026-09-18, DRAFT Étape 8)** : le ROADMAP listait `transform: Transform` sur `Mesh`. > **Déviation validée : `transform` reste sur `Entity` et n'est PAS ajouté à `Mesh`.** Un mesh est > **partagé** par plusieurs entités à des transforms différents (modèle instancé, Étape 4/7) : un > `transform` unique sur `Mesh` casserait ce modèle. L'Étape 8 met donc en œuvre le refactor de > *stockage CPU* (`Mesh.geometry: Arc` + buffers dérivés) **sans** le champ `transform`. +> *(Implémenté 2026-09-18.)* ### 1.3 Shader Phong Minimal - [x] Créer `standard_shader.wgsl` (Étape 2, 2026-09-16) : diff --git a/lib/src/resources/README.md b/lib/src/resources/README.md index 836d68a..e1f531d 100644 --- a/lib/src/resources/README.md +++ b/lib/src/resources/README.md @@ -7,7 +7,7 @@ The `resources` module defines three immutable data types that flow through the | File | Responsibility | |------|---------------| | **vertex** | Vertex struct — CPU-side per-attribute tuple (position [f32;3], normal [f32;3], uv [f32;2], color [f32;4]). Must match PipelineCache::build_pipeline() vertex buffer layout byte-for-byte. | -| **mesh** | Mesh struct — persistent GPU geometry container with vertex_buffer (wgpu::Buffer), optional index_buffer, and draw call counters. Created via Mesh::new() which uploads data from CPU to GPU buffers. | +| **mesh** | Mesh struct — persistent GPU geometry container with retained CPU `geometry: Arc` (Étape 8), vertex_buffer (wgpu::Buffer), optional index_buffer, and draw call counters. Created via Mesh::from_geometry() which derives Vertex arrays from the Geometry and uploads them to GPU buffers. | | **material** | Material struct — lightweight appearance descriptor pairing shader_id with a shared RenderPipeline Arc. Multiple Materials referencing the same shader_id point to the identical compiled GPU pipeline. | ## Interaction with Other Modules