summaryrefslogtreecommitdiff
path: root/src/3d
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 /src/3d
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 'src/3d')
-rw-r--r--src/3d/renderer.h8
-rw-r--r--src/3d/renderer_pipelines.cc1
2 files changed, 3 insertions, 6 deletions
diff --git a/src/3d/renderer.h b/src/3d/renderer.h
index 4c31c97..11a7931 100644
--- a/src/3d/renderer.h
+++ b/src/3d/renderer.h
@@ -24,12 +24,9 @@ struct GlobalUniforms {
vec2 resolution;
vec2 padding;
- // Transpose matrices: mini_math is row-major, WGSL expects column-major.
static GlobalUniforms make(const mat4& vp, const vec4& cam_pos_time,
const vec4& p, const vec2& res) {
- return {mat4::transpose(vp), mat4::transpose(vp.inverse()),
- cam_pos_time, p,
- res, vec2(0.0f, 0.0f)};
+ return {vp, vp.inverse(), cam_pos_time, p, res, vec2(0.0f, 0.0f)};
}
};
@@ -42,9 +39,8 @@ struct ObjectData {
// applicable)
vec4 params;
- // Transpose matrices: mini_math is row-major, WGSL expects column-major.
static ObjectData make(const mat4& m, const vec4& col, const vec4& p) {
- return {mat4::transpose(m), mat4::transpose(m.inverse()), col, p};
+ return {m, m.inverse(), col, p};
}
};
diff --git a/src/3d/renderer_pipelines.cc b/src/3d/renderer_pipelines.cc
index be4a317..2950a7f 100644
--- a/src/3d/renderer_pipelines.cc
+++ b/src/3d/renderer_pipelines.cc
@@ -249,6 +249,7 @@ void Renderer3D::create_mesh_pipeline() {
pipeline_desc.vertex.buffers = &vert_buffer_layout;
pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
pipeline_desc.primitive.cullMode = WGPUCullMode_Back;
+ pipeline_desc.primitive.frontFace = WGPUFrontFace_CW; // Y-flipped perspective
pipeline_desc.multisample.count = 1;
pipeline_desc.fragment = &fragment_state;
pipeline_desc.depthStencil = &depth_stencil;