3de84aa4dc
D1 placeholder 1×1 + groupe 2 sur toutes les pipelines · D2 échantillonnage inconditionnel · D3 image + Rgba8UnormSrgb · D4 Material propriétaire du bind group. Suite : implémentation 10.1-10.5 (refactor) puis docs (10.6).
6.6 KiB
6.6 KiB
DRAFT — Étape 10 : Textures (Phase 4.1)
📅 Rédigé le 2026-09-18. Plan à valider avant implémentation. Source de vérité = code + README.md. Ce document est vidé à la complétion de l'étape.
Contexte (état de départ)
La Phase 4.1 (Textures) du ROADMAP vise à texturer le rendu. État actuel du code :
- La tuyauterie UV existe déjà :
Geometry.uvs: Option<Vec<[f32; 2]>>(builderwith_uvs) etVertex.uv(location 2, offset 24, stride 56) sont déclarés dansbuild_pipelineet lus par le shaderVertexInput. Seul l'échantillonnage manque. - Le shader
standard_shader.wgslreçoit l'UV mais ne le transmet pas au fragment et n'échantillonne rien. - Aucun type
Texture, aucun sampler, aucun bind group de texture.Materialne porte pas de texture. - Architecture bind group : « un seul layout pour tous » (Étape 3) — les groupes
frame @0object @1sont posés sur toutes les pipelines et bindés à chaque draw (draw_entity).
Conclusion : l'UV est prête ; les pièces manquantes sont un type Texture, un bind group de
texture (groupe 2) partagé, un échantillonnage dans le shader et le portage sur Material.
Objectif
Permettre de texturer un mesh : charger une image → wgpu::Texture (+ view + sampler), lier une
texture diffuse à un Material, échantillonner dans le shader, sans casser le pattern « un seul
layout pour tous ».
Décisions (actées le 2026-09-18)
- [x] D1 (intégration bind group — « un seul layout pour tous ») : on ajoute un 3ᵉ bind group
@group(2)(sampler + texture diffuse) posé sur toutes les pipelines, avec une texture blanche 1×1 de secours (placeholder) utilisée quand unMaterialn'a pas de texture. Cela préserve l'unicité du layout (aucune pipeline multiple), donc un seul flux de rendu. (alternative écartée : bind group optionnel → casse l'unicité du layout, refactor de toutes les pipelines). - [x] D2 (échantillonnage inconditionnel) : le fragment shader échantillonne toujours la
texture diffuse ; le placeholder blanc (texel = 1) reproduit exactement le comportement actuel
d'un material sans texture. Donc pas de flag conditionnel → un seul flow de shader. En mode lit,
le texel remplace la couleur du vertex (
texel.rgb * (ambient + diffuse)) ; en unlit, le texel tel quel. Symétrique du pattern unlit existant. - [x] D3 (chargement d'image & format) : ajouter la dépendance
image(décodage PNG/JPEG) àlib/Cargo.toml; upload enTextureFormat::Rgba8UnormSrgb, usageTEXTURE_BINDING | COPY_DST, dimensionD2,mip_level_count: 1(YAGNI : pas de génération de mipmaps cette étape), samplerfilter: Linear,address_mode: Repeat. - [x] D4 (API et portage) : nouveau type
Texture(device + view + sampler).Materialgagnetexture: Option<Arc<Texture>>et détient son bind group de texture (groupe 2), construit depuis le layout partagé ; sans texture il lie le placeholder. APIScene:add_texture(id, tex)et liaison d'une texture à un material.draw_entitybindset_bind_group(2, ...).
Plan d'implémentation
10.1 — Nouveau type Texture + dépendance image
- Ajouter
imageàlib/Cargo.toml(featurespng,jpeg). resources::texture::Texture { texture: wgpu::Texture, view: wgpu::TextureView, sampler: wgpu::Sampler }.Texture::from_bytes(device, queue, &[u8])(oufrom_file) : décode viaimage, remplit un buffer RGBA et upload viaQueue::write_texture(D3).Texture::white_placeholder(device, queue): 1×1 blanc, pour D1/D2.- Enregistrer
pub mod texturedansresources/mod.rs.
10.2 — Bind group layout texture (groupe 2) partagé
create_uniform_bind_group_layoutsretourne[frame, object, texture](3 layouts) ;texture=BindingType::Sampler(Filtering)(binding 0) +Texture { sample_type: Float, view_dimension: D2 }(binding 1), visibilité fragment.build_pipeline: ajouter le 3ᵉ layout auPipelineLayoutDescriptor(l'unicité du layout est conservée — D1).- Mettre à jour les destructures
let [frame_layout, object_layout](renderer.rs) pour 3 éléments.
10.3 — Shader standard : UV → fragment + échantillonnage
VertexOutput: ajouter@location(2) uv: vec2<f32>;vs_mainécritout.uv = input.uv.- Déclarer
@group(2) @binding(0) var texture_sampler: sampler;et@group(2) @binding(1) var diffuse_texture: texture_2d<f32>;. fs_main:let texel = textureSample(diffuse_texture, texture_sampler, in.uv);— en lit →texel.rgb * (ambient + diffuse), en unlit →texel(D2). Mettre à jour la doc du module shader.
10.4 — Material porte la texture diffuse
Material { texture: Option<Arc<Texture>>, texture_bind_group }; le constructeur construit le bind group (groupe 2) depuis le layout partagé, avec placeholder siNone(D1/D4).- Méthode
set_texture(...)qui recrée le bind group si la texture change. - Le sampler/placeholder partagé est fourni par la lib (une seule instanciation) pour que tout Material sans texture lie le blanc.
10.5 — API Scene & binding dans draw_entity
- Rendre accessible un layout du groupe 2 aux Materials (via
SceneGpu/ cache) pour construire leurs bind groups. - Route déclarative
Scene:add_texture(id, tex)et liaison d'une texture par id à un material (ex.add_material_textureou paramètre deadd_material_shader). draw_entity:pass.set_bind_group(2, material.texture_bind_group, &[]).- Vérifier qu'un material sans texture continue de fonctionner (placeholder → aucune régression).
10.6 — Exemples + validation
cube: texturer le cube (image PNG embarquée viainclude_bytes!pour rester autonome, ou un motif procédural RGBA généré en mémoire).simple/manual: pas de régression (placeholder).cargo fmt --all,cargo check --workspace(0 warning),cargo test --workspace(vert, tests de layout uniform + validation WGSL à jour),cargo doc(pas demissing_docs).- Exécuter
cube(faces texturées) etsimplesans erreur backend.
Point d'étape
- Valider D1–D4 avant implémentation. (actées le 2026-09-18)
- Caser 10.1–10.6, validation verte, exemples OK.
- Deux commits séparés :
refactor(...)(10.1–10.5) puisdocs(...)(10.6) + README/DRAFT. - Rédiger le bilan et ouvrir la suite (Phase 4.2 Éclairage avancé).
Fin du DRAFT Étape 10 — à valider avant implémentation.