docs(étape8): valider et documenter le refactor stockage CPU Arc<Geometry> (8.6)
- 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.
This commit is contained in:
@@ -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<Geometry>` 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<Geometry>`, `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<Geometry>` 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<Geometry>` (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.)
|
||||
|
||||
+42
-19
@@ -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<Geometry>`. É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<Geometry>` + 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<Vec<[f32; 4]>>` 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<Vertex>`
|
||||
|
||||
- [ ] 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<Vertex>` 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<Geometry>` et construit ses buffers
|
||||
|
||||
- [ ] Dans `lib/src/resources/mesh.rs` :
|
||||
- [x] Dans `lib/src/resources/mesh.rs` :
|
||||
- [ ] ajouter le champ `geometry: Arc<Geometry>`.
|
||||
- [ ] remplacer/ajouter `Mesh::from_geometry(device: &wgpu::Device, geometry: Arc<Geometry>,
|
||||
material: Option<Arc<Material>>) -> 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<Geometry>`, 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<Vertex>` / `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<Geometry>, 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<Geometry>` + buffers dérivés, API `create_mesh`
|
||||
- [x] Caser le refactor : `Mesh.geometry: Arc<Geometry>` + 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<Geometry>` (CPU, D5) + buffers GPU pré-uploadés ;
|
||||
constructeur **unique** `Mesh::from_geometry(device, Arc<Geometry>, Option<Arc<Material>>)`
|
||||
(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<Geometry>` 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._
|
||||
|
||||
+6
-2
@@ -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<Geometry>`) :
|
||||
> `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)
|
||||
|
||||
|
||||
+15
-10
@@ -53,24 +53,29 @@ generated: { by: human:jerome, at: 2026-07-31T00:00:00Z }
|
||||
- [x] `positions: Vec<[f32; 3]>` (obligatoire)
|
||||
- [x] `indices: Option<Vec<u16>>` (optionnel)
|
||||
- [x] `normals: Option<Vec<[f32; 3]>>` (pour Phong) — plus `uvs: Option<Vec<[f32; 2]>>`
|
||||
- [ ] `colors: Option<Vec<[f32; 4]>>` — **décidé en DRAFT Étape 8 (D1)** : le shader lit la couleur
|
||||
unlit, il faut la porter dans `Geometry` ; conversion `Geometry -> Vec<Vertex>` pour l'upload.
|
||||
- [ ] Refactorer `Mesh` pour contenir :
|
||||
- [ ] `geometry: Arc<Geometry>`
|
||||
- [ ] `vertex_buffer: wgpu::Buffer`
|
||||
- [ ] `index_buffer: Option<wgpu::Buffer>`
|
||||
- [x] `colors: Option<Vec<[f32; 4]>>` — **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<Vertex>` via `Geometry::to_vertices()` (D6) pour l'upload.
|
||||
- [x] Refactorer `Mesh` pour contenir — **fait (Étape 8, 8.3, 2026-09-18)** :
|
||||
- [x] `geometry: Arc<Geometry>` (rétention CPU, D5) + accesseur `geometry()`
|
||||
- [x] `vertex_buffer: wgpu::Buffer`
|
||||
- [x] `index_buffer: Option<wgpu::Buffer>`
|
||||
- Construction via `Mesh::from_geometry(device, Arc<Geometry>, 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<Geometry>` » 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<Arc<Material>>` (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<Arc<Material>>` (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<Geometry>` + 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) :
|
||||
|
||||
@@ -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<Geometry>` (É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
|
||||
|
||||
Reference in New Issue
Block a user