diff options
| author | skal <pascal.massimino@gmail.com> | 2026-03-08 11:36:04 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-03-08 11:36:04 +0100 |
| commit | ba7ea27ddee4398afa98a0e45b9e227bbcfae906 (patch) | |
| tree | 09f8bb60c324aad53c829d79f50f56497cd1d7be /src/effects | |
| parent | 1ad5057ce8e68e57340aae3442b2c6b787409ad3 (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 'src/effects')
| -rw-r--r-- | src/effects/ntsc.wgsl | 2 | ||||
| -rw-r--r-- | src/effects/rotating_cube_effect.cc | 1 | ||||
| -rw-r--r-- | src/effects/rotating_cube_effect.h | 5 |
3 files changed, 4 insertions, 4 deletions
diff --git a/src/effects/ntsc.wgsl b/src/effects/ntsc.wgsl index 5c27695..4e72f0a 100644 --- a/src/effects/ntsc.wgsl +++ b/src/effects/ntsc.wgsl @@ -2,6 +2,7 @@ #include "sequence_uniforms" #include "render/fullscreen_uv_vs" #include "math/noise" +#include "debug/debug_print" const vignetteRounding = 160.0f; const vignetteSmoothness = 0.7f; @@ -68,5 +69,6 @@ fn vignette(uv: vec2f) -> f32 { col.g *= 1.01; col.b *= 0.94; + col = debug_f32(col, in.position.xy / uniforms.resolution, vec2f(10., 10.), 3.2); return vec4f(clamp(col, vec3f(0.0), vec3f(1.0)), 1.0); } diff --git a/src/effects/rotating_cube_effect.cc b/src/effects/rotating_cube_effect.cc index 757d64c..197bc26 100644 --- a/src/effects/rotating_cube_effect.cc +++ b/src/effects/rotating_cube_effect.cc @@ -75,6 +75,7 @@ RotatingCube::RotatingCube(const GpuContext& ctx, pipeline_desc.vertex.entryPoint = str_view("vs_main"); pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList; pipeline_desc.primitive.cullMode = WGPUCullMode_Back; + pipeline_desc.primitive.frontFace = WGPUFrontFace_CW; // Y-flipped perspective pipeline_desc.depthStencil = &depth_stencil; pipeline_desc.multisample.count = 1; pipeline_desc.multisample.mask = 0xFFFFFFFF; diff --git a/src/effects/rotating_cube_effect.h b/src/effects/rotating_cube_effect.h index 920be5c..fb321fa 100644 --- a/src/effects/rotating_cube_effect.h +++ b/src/effects/rotating_cube_effect.h @@ -29,12 +29,9 @@ class RotatingCube : public Effect { float aspect_ratio; float _pad; - // Transpose matrices: mini_math is row-major, WGSL expects column-major. static Uniforms make(const mat4& vp, const vec4& cam_pos_time, const vec4& p, const vec2& res, float asp) { - return {mat4::transpose(vp), mat4::transpose(vp.inverse()), - cam_pos_time, p, - res, asp}; + return {vp, vp.inverse(), cam_pos_time, p, res, asp}; } }; static_assert(sizeof(Uniforms) == 176, "Uniforms size mismatch"); |
