feat(examples): 3D MVP cube via standard shader, drop basic (Étape 5)

This commit is contained in:
Jérôme Bousquié
2026-09-17 10:40:43 +02:00
parent 43e8bfb40a
commit 0a85aff17b
15 changed files with 218 additions and 111 deletions
+12 -25
View File
@@ -2,39 +2,24 @@
## Overview
Contains WGSL shader source files used by the PipelineCache module. These are loaded at runtime from disk when referenced by their registered ID in PipelineCache.register_shader(). If a file is missing, PipelineCache falls back to the embedded BASIC_SHADER constant defined in utils::conf.
Contains WGSL shader source files used by the PipelineCache module. These are loaded at runtime from
disk when referenced by their registered ID in PipelineCache.register_shader(). If a file is missing,
PipelineCache falls back to the embedded STANDARD_SHADER constant defined in utils::conf.
Depuis l'Étape 5, il n'existe plus qu'**un seul shader** : `standard_shader.wgsl` (Phong). L'ancien
`basic_shader.wgsl` a été supprimé comme pipeline séparé — le rendu 2D plat est désormais la **variante
unlit** de `standard` (décision actée dans le DRAFT : « 2D ⊂ 3D »).
## Files
| File | Purpose |
|------|---------|
| **basic_shader.wgsl** | Legacy flat/unlit vertex/fragment shader pair (vs_main / fs_main) with position, uv, and color attributes. Scheduled to be replaced by the unlit variant of `standard_shader.wgsl` (DRAFT Étape 2.3 / 5). |
| **standard_shader.wgsl** | Standard (Phong) vertex/fragment shader — ambient + directional diffuse with an explicit unlit mode. Carries the full uniform contract (frame @group(0) + object @group(1)). |
## Shader Contract (basic_shader.wgsl)
The WGSL shader defines:
- `@vertex fn vs_main(model: VertexInput) -> VertexOutput` — vertex entry point
- `@fragment fn fs_main(in: VertexOutput) -> @location(0) vec4<f32>` — fragment entry point writing RGBA output
### Vertex Input Layout
| Location | Attribute | Type | Offset (bytes) |
|----------|-----------|------|----------------|
| 0 | position | vec3<f32> | 0 |
| 1 | uv | vec2<f32> | 12 |
| 2 | color | vec3<f32> | 24 |
**Note**: This shader uses a 39-byte vertex stride (3+2+3 floats). It does NOT include normal data or alpha channel interpolation — it outputs fully opaque geometry with per-vertex color passthrough. This differs from the full `Vertex` struct layout (56 bytes with normal + alpha) defined in resources::Vertex; if a full shader matching the Vertex struct is needed, extend this shader accordingly.
> **Statut** : ce shader n'est plus un pipeline séparé ; il est destiné à disparaître au profit de la variante
> unlit de `standard_shader.wgsl` (DRAFT Étape 2.3 / Étape 5, « un seul layout pour tous »).
## Shader Contract (standard_shader.wgsl)
`standard_shader.wgsl` est le shader unifié (Phong) de WSG. Il corrige le défaut latente de `basic`
(contrat vertex incomplet) et expose les deux bind groups partagés par tout matériau.
`standard_shader.wgsl` est le shader unifié (Phong) de WSG. Il expose les deux bind groups partagés
par tout matériau (Étape 3 : un seul layout pour tous).
### Vertex Input Layout (56-byte stride — correspond au `resources::Vertex`)
@@ -57,4 +42,6 @@ The WGSL shader defines:
### Mode unlit
Un flag `options.x != 0` neutralise la directionnelle et renvoie la couleur du vertex telle quelle
(couleur plate). Ainsi le rendu 2D plat est un **cas particulier** de la 3D éclairée.
(couleur plate). Côté API, `Renderer::set_unlit(true)` (ou `app.renderer_mut().set_unlit(true)`)
positionne ce flag dans les frame uniforms. Ainsi le rendu 2D plat est un **cas particulier** de la 3D
éclairée.
-42
View File
@@ -1,42 +0,0 @@
//! # Basic Shader Module
//!
//! Default vertex/fragment shader pair used by PipelineCache when no external .wgsl file is found.
//! This shader implements a simple unlit rendering path: passes through position and color attributes
//! from VertexInput to fragment output, producing flat-colored geometry without lighting calculations.
//!
//! ## Shader Contract
//! Must define entry points matching PipelineCache::build_pipeline():
//! - @vertex fn vs_main(model: VertexInput) -> VertexOutput
//! - model.position → @location(0), vec3<f32>, offset 0 bytes in vertex buffer
//! - model.uv → @location(1), vec2<f32>, offset 12 bytes in vertex buffer
//! - model.color → @location(2), vec3<f32>, offset 24 bytes in vertex buffer
//! - @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4<f32>
//! - Writes RGBA output where alpha is hardcoded to 1.0 (fully opaque).
//!
//! ## Technical Notes
//! - No normal or UV interpolation — this is an unlit shader that directly outputs the per-vertex color.
//! - The clip_position is computed as vec4<f32>(position, 1.0), assuming position is already in NDC space.
struct VertexInput {
@location(0) position: vec3<f32>,
@location(1) uv: vec2<f32>,
@location(2) color: vec3<f32>,
};
struct VertexOutput {
@builtin(position) clip_position: vec4<f32>,
@location(0) color: vec3<f32>,
};
@vertex
fn vs_main(model: VertexInput) -> VertexOutput {
var out: VertexOutput;
out.clip_position = vec4<f32>(model.position, 1.0);
out.color = model.color; // On transmet la couleur au fragment shader
return out;
}
@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
return vec4<f32>(in.color, 1.0);
}