summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-03-08 11:36:04 +0100
committerskal <pascal.massimino@gmail.com>2026-03-08 11:36:04 +0100
commitba7ea27ddee4398afa98a0e45b9e227bbcfae906 (patch)
tree09f8bb60c324aad53c829d79f50f56497cd1d7be /doc
parent1ad5057ce8e68e57340aae3442b2c6b787409ad3 (diff)
fix: negate Y in perspective() to correct rasterized 3D orientation
The fullscreen post-process VS uses Y-up UVs (uv.y=0 = bottom), so textureSample() Y-flips any rasterized offscreen texture. SDF effects author their content Y-down and look correct after the flip. Rasterized effects (RotatingCube, Hybrid3D) must pre-flip their geometry: - mat4::perspective(): m[5] = -t (negated Y scale) - Pipelines with cullMode=Back: frontFace = WGPUFrontFace_CW (Y-flip reverses winding, so CW becomes the visible face) - Remove incorrect transposes from GlobalUniforms::make(), ObjectData::make(), and Uniforms::make() — mini_math is column-major, no transpose needed for GPU upload - Document the convention in doc/3D.md under "Rasterized 3D and the Y-flip rule" handoff(Gemini): Y-flip rule now documented; all rasterized 3D pipelines must follow it. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'doc')
-rw-r--r--doc/3D.md17
1 files changed, 17 insertions, 0 deletions
diff --git a/doc/3D.md b/doc/3D.md
index c27b034..dbcd6f9 100644
--- a/doc/3D.md
+++ b/doc/3D.md
@@ -24,6 +24,23 @@
- WebGPU framebuffer: y-down (pixel row 0 at top)
- `uv.y = 0` → NDC `y = -1` → bottom of framebuffer ✓
+### Rasterized 3D and the Y-flip rule
+
+The fullscreen post-process VS (`fullscreen_uv_vs.wgsl`) uses **Y-up UVs** (`uv.y=0` = bottom of screen).
+`textureSample(tex, s, uv)` with those UVs samples the **top** of the input texture at the bottom of
+the screen — a Y-flip. SDF effects are authored Y-down and appear correct after this flip. Rasterized
+effects (RotatingCube, Hybrid3D) render into an offscreen texture and are consumed by the post-process
+chain, so they must **pre-flip** their geometry to compensate:
+
+- **`mat4::perspective()`** uses `m[5] = -t` (negated Y scale) — renders geometry upside-down into the
+ texture so the post-process chain flips it right-side up.
+- **Rasterized pipelines** with `cullMode = Back` must set `frontFace = WGPUFrontFace_CW` — the Y-flip
+ reverses winding order on screen, so CW becomes the visible (front) face.
+- Pipelines with `cullMode = None` (SDF proxy hull, skybox) need no winding change.
+
+**Do not** set `m[5] = +t` or use `frontFace = WGPUFrontFace_CCW` (default) in rasterized 3D
+pipelines — the result will be upside-down with back-faces culled.
+
## Core Concept
Hybrid SDF/rasterization pipeline with physics and collision detection.