fix(shadow): make Étape 14 shadow visible
The shadow pass was correct but the demo light was much too steep (52° elevation), so the blocker's shadow fell in a ~0.5-unit sliver tight against the cube's base and was invisible against the bright ground (offscreen pixel probe found a single dark pixel). Verified with an offscreen probe using the real Renderer::render_scene + shadow path: - steep front light (0.6,1.1,0.6) -> 1 dark pixel (no visible shadow) - shallow side light (1.0,0.3,0.0) -> 17 107 pixels (shadow pipeline OK) - tuned front-right (1.0,0.5,0.0) -> 16 979 pixels (clear visible shadow) The azimuth matters most: from the elevated front-right camera, a shadow cast toward -z falls behind the cube and is occluded; one cast toward -x runs across the ground to the left of the cube and reads clearly. Tuned light therefore sits front-right and low (toward_light (1.0,0.5,0.0)), keeping the front faces lit while casting a clearly visible PCF-softened shadow. Also reapply the LessEqual comparison sampler fix (commit39167eehad set it, but was later reverted to GreaterEqual by9a51ff7while debugging; the probe confirms LessEqual is the correct, non-inverted test). Correct 'rotating cube' to 'cube' in README/ROADMAP (shadow_test scene is static).
This commit is contained in:
@@ -188,4 +188,4 @@ The architecture docs live in `docs/tech/` and are written in **French**. Each d
|
||||
9. ✅ **Window resize (Étape 11, Phase 4.4)** — `App::resize` reconfigures the surface (`Context::configure`) and recreates the depth texture (`Renderer::resize_depth`) together on each `WindowEvent::Resized`, so color and depth attachments always match. Guards against 0×0 (minimize). The surface format is re-synced to the Renderer and Scene if it ever changes. (Done 2026-09-18; verified at runtime on the `cube` example.)
|
||||
10. ✅ **Multi-lighting (Étape 12, Phase 4.2)** — the scene now carries a global light list (directional + point) with a white ambient, uploaded into the per-frame `FrameUniforms` array each frame. `Scene::add_directional_light` / `add_point_light` / `set_ambient` / `clear_lights` configure it; `FrameUniforms::default()` (one white directional along +Z + white ambient) reproduces the pre-multi-light look exactly. The `standard` fragment accumulates ambient + all lights; the `cube` example adds a warm point light on top of the default directional. (Done 2026-09-18.)
|
||||
11. ✅ **Spot lights (Étape 13, Phase 4.2)** — spot lights (oriented cone + half-angle) added on top of the multi-lighting system. `Scene::add_spot_light(pos, dir, color, intensity, radius, half_angle)` registers a spot light; the `standard` fragment accumulates a spot term with a smoothed penumbra (half-angle ± 0.1 rad) and linear attenuation. `Light` grew from 48 to 64 bytes (added `dir_angle`); `FrameUniforms` from 576 to 704 bytes (added `num_spot`). Non-regression: default scene unchanged. The `cube` example adds a green spot light aimed at the cube. (Done 2026-09-18.)
|
||||
12. ✅ **Shadows — shadow mapping (Étape 14, Phase 4.2, optionnel)** — classic two-pass shadow mapping on a **single** light (directional or spot), selected by `Scene::set_shadow_caster(index)`. A depth-only pass (`shadow_shader.wgsl` + dedicated `shadow_pipeline`) renders the scene into a 1024² `Depth32Float` shadow map (`Renderer`-owned, slope-scaled depth bias); the `standard` fragment re-projects each fragment into light space and applies a **PCF 3×3** comparison-sampler test (bind group **@3**, shared). `FrameUniforms` grew from 704 to 784 bytes (`shadow_light_index`, `light_view_proj`, `shadow_params`). Shadows are **off by default** (`shadow_caster = None`) so `simple`/`cube`/`manual`/`spot_test` are unchanged. The `shadow_test` example casts a soft shadow from a rotating cube onto a ground slab. (Done 2026-09-19.)
|
||||
12. ✅ **Shadows — shadow mapping (Étape 14, Phase 4.2, optionnel)** — classic two-pass shadow mapping on a **single** light (directional or spot), selected by `Scene::set_shadow_caster(index)`. A depth-only pass (`shadow_shader.wgsl` + dedicated `shadow_pipeline`) renders the scene into a 1024² `Depth32Float` shadow map (`Renderer`-owned, slope-scaled depth bias); the `standard` fragment re-projects each fragment into light space and applies a **PCF 3×3** comparison-sampler test (bind group **@3**, shared). `FrameUniforms` grew from 704 to 784 bytes (`shadow_light_index`, `light_view_proj`, `shadow_params`). Shadows are **off by default** (`shadow_caster = None`) so `simple`/`cube`/`manual`/`spot_test` are unchanged. The `shadow_test` example casts a soft shadow from a cube onto a ground slab. (Done 2026-09-19.)
|
||||
|
||||
Reference in New Issue
Block a user