You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This tutorial builds a reflective floor using the stencil buffer with an optional depth test and 4× multi‑sample anti‑aliasing (MSAA). The scene renders in four phases: a floor mask into stencil, a mirrored cube clipped by the mask, a tinted floor surface, and a normal cube above the plane.
19
+
This tutorial builds a reflective floor using the stencil buffer with an optional depth test and 4× multi‑sample anti‑aliasing (MSAA). The scene renders in four phases: a floor mask into stencil, a mirrored cube clipped by the mask, a translucent lit floor surface, and a normal cube above the plane. The camera looks down at a moderate angle so the reflection is clearly visible.
- A pipeline that uses stencil state MUST render into a pass with a depth‑stencil attachment. Use `DepthFormat::Depth24PlusStencil8`.
61
61
- The mask pass MUST disable depth writes and write stencil with `Replace` so the floor area becomes `1`.
62
62
- The reflected cube pipeline MUST test stencil `Equal` against reference `1` and SHOULD set stencil write mask to `0x00`.
63
-
- Mirroring across the floor plane flips face winding. Culling MUST be disabled for the reflected draw or the front‑face definition MUST be adjusted. This example disables culling.
63
+
- Mirroring across the floor plane flips face winding. Culling MUST be disabled for the reflected draw or the front‑face definition MUST be adjusted. This example culls front faces for the reflected cube.
64
64
- Push constant size and stage visibility MUST match the shader declaration. Two `mat4` values are sent to the vertex stage only (128 bytes total).
65
65
- Matrix order MUST match the shader’s expectation. The example transposes matrices before upload to match GLSL column‑major multiplication.
66
66
- The render pass and pipelines MUST use the same sample count when MSAA is enabled.
@@ -78,7 +78,7 @@ Pass 1: Depth/Stencil‑only (no color) — write stencil where floor covers
Narrative: The component stores GPU handles and toggles. When settings change, mark `needs_rebuild = true` and rebuild pipelines/passes on the next frame.
125
125
126
126
### Step 2 — Shaders and Push Constants <aname="step-2"></a>
127
-
Use one vertex shader and two fragment shaders. The vertex shader expects push constants with two `mat4` values: the MVP and the model matrix, used to transform positions and rotate normals to world space.
127
+
Use one vertex shader and two fragment shaders. The vertex shader expects push constants with two `mat4` values: the MVP and the model matrix, used to transform positions and rotate normals to world space. The floor fragment shader is lit and translucent so the reflection reads beneath it.
Render the mirrored cube only where the floor mask is present. Disable culling to avoid flipped winding after mirroring. Preserve depth testing configuration via toggles.
238
+
Render the mirrored cube only where the floor mask is present. Mirroring flips the winding, so cull front faces for the reflected draw. Use `depth_compare = Always` and disable depth writes so the reflection remains visible; the stencil confines it to the floor.
### Step 9 — Per‑Frame Transforms and Reflection <aname="step-9"></a>
295
-
Compute camera, model rotation, and the mirror transform across the floor plane. The reflection scales Y by −1 and translates downward to align with the mirrored cube below the floor.
300
+
Compute camera, model rotation, and the mirror transform across the floor plane. The camera pitches downward and translates to a higher vantage point. Build the mirror using the plane‑reflection matrix `R = I − 2 n n^T` for a plane through the origin with unit normal `n` (for a flat floor, `n = (0,1,0)`).
- A cube rotates above a reflective floor. The reflection appears only inside the floor area and shows correct mirroring.
372
387
- Press `S` to toggle the reflection (stencil). The reflected cube disappears when stencil is off.
373
-
- Press `D` to toggle depth testing. With depth off, the reflection still clips to the floor via stencil, but depth ordering may show artifacts if geometry overlaps.
374
-
- Press `M` to toggle MSAA. With `4×` MSAA, edges appear smoother; with `1×`, edges appear more aliased.
388
+
- Press `F` to hide/show the floor overlay to see a clean mirror.
389
+
- Press `I`/`K` to adjust camera pitch; ensure the reflection remains visible at moderate angles.
390
+
- Press `D` to toggle depth testing. With depth off, the reflection still clips to the floor via stencil.
391
+
- Press `M` to toggle MSAA. With `4×` MSAA, edges appear smoother.
375
392
376
393
## Notes <aname="notes"></a>
377
394
378
395
- Pipelines that use stencil MUST target a pass with a depth‑stencil attachment; otherwise, pipeline creation or draws will fail.
379
396
- Mirroring across a plane flips winding. Either disable culling or adjust front‑face winding for the reflected draw; do not leave back‑face culling enabled with mirrored geometry.
397
+
- This implementation culls front faces for the reflected pipeline to account for mirrored winding; the normal cube uses back‑face culling.
380
398
- The mask pass SHOULD clear stencil to `0` and write `1` where the floor renders. Use `Replace` and a write mask of `0xFF`.
381
399
- The reflected draw SHOULD use `read_mask = 0xFF`, `write_mask = 0x00`, and `reference = 1` to preserve the mask.
382
400
- When depth testing is disabled, set `depth_compare = Always` and `depth_write = false` to avoid unintended depth interactions.
383
401
- The pass and all pipelines in the pass MUST use the same MSAA sample count.
384
402
- Transpose matrices before uploading when GLSL expects column‑major multiplication.
403
+
- Metal (MSL) portability: avoid calling `inverse()` in shaders for normal transforms; compute the normal matrix on the CPU if needed. The example uses `mat3(model)` for rigid + mirror transforms.
385
404
386
405
## Conclusion <aname="conclusion"></a>
387
406
@@ -403,4 +422,5 @@ The reflective floor combines a simple stencil mask with an optional depth test
403
422
404
423
## Changelog <aname="changelog"></a>
405
424
425
+
- 0.2.0 (2025‑11‑19): Updated for camera pitch, front‑face culling on reflection, lit translucent floor, unmasked reflection debug toggle, floor overlay toggle, and Metal portability note.
406
426
- 0.1.0 (2025‑11‑17): Initial draft aligned with `crates/lambda-rs/examples/reflective_room.rs`, including stencil mask pass, reflected pipeline, and MSAA/depth toggles.
0 commit comments