summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/3d/renderer.h5
-rw-r--r--src/3d/renderer_draw.cc9
-rw-r--r--src/3d/renderer_pipelines.cc5
-rw-r--r--src/tests/3d/test_3d_render.cc1
4 files changed, 16 insertions, 4 deletions
diff --git a/src/3d/renderer.h b/src/3d/renderer.h
index 11a7931..8f933b5 100644
--- a/src/3d/renderer.h
+++ b/src/3d/renderer.h
@@ -78,6 +78,10 @@ class Renderer3D {
bvh_enabled_ = enabled;
}
+ // Call before init(). When true, renders directly to surface (no post-process
+ // Y-flip): uses standard perspective (Y not negated) and CCW winding.
+ void set_direct_render(bool v) { direct_render_ = v; }
+
struct MeshGpuData {
WGPUBuffer vertex_buffer;
WGPUBuffer index_buffer;
@@ -120,6 +124,7 @@ class Renderer3D {
BVH cpu_bvh_; // Keep a CPU-side copy for building/uploading
bool bvh_enabled_ = true;
+ bool direct_render_ = false; // true = render to surface (no post-process flip)
std::map<AssetId, MeshGpuData> mesh_cache_;
const MeshGpuData* temp_mesh_override_ = nullptr; // HACK for test_mesh tool
diff --git a/src/3d/renderer_draw.cc b/src/3d/renderer_draw.cc
index d4a35a8..dca7113 100644
--- a/src/3d/renderer_draw.cc
+++ b/src/3d/renderer_draw.cc
@@ -9,7 +9,9 @@
void Renderer3D::update_uniforms(const Scene& scene, const Camera& camera,
float time) {
- const mat4 vp = camera.get_projection_matrix() * camera.get_view_matrix();
+ mat4 proj = camera.get_projection_matrix();
+ if (direct_render_) proj.m[5] = -proj.m[5]; // undo Y-negate for direct surface
+ const mat4 vp = proj * camera.get_view_matrix();
const GlobalUniforms globals = GlobalUniforms::make(
vp,
vec4(camera.position.x, camera.position.y, camera.position.z, time),
@@ -203,8 +205,9 @@ void Renderer3D::draw(WGPURenderPassEncoder pass, const Scene& scene,
}
}
- // Calculate ViewProj matrix for the debug renderer
- mat4 view_proj = camera.get_projection_matrix() * camera.get_view_matrix();
+ mat4 dbg_proj = camera.get_projection_matrix();
+ if (direct_render_) dbg_proj.m[5] = -dbg_proj.m[5];
+ mat4 view_proj = dbg_proj * camera.get_view_matrix();
visual_debug_.render(pass, view_proj);
}
#endif
diff --git a/src/3d/renderer_pipelines.cc b/src/3d/renderer_pipelines.cc
index 3abc3bd..195baad 100644
--- a/src/3d/renderer_pipelines.cc
+++ b/src/3d/renderer_pipelines.cc
@@ -253,7 +253,10 @@ 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
+ // CW winding compensates for Y-negation in perspective() (post-process chain).
+ // Direct-to-surface rendering uses standard CCW winding.
+ pipeline_desc.primitive.frontFace =
+ direct_render_ ? WGPUFrontFace_CCW : WGPUFrontFace_CW;
pipeline_desc.multisample.count = 1;
pipeline_desc.fragment = &fragment_state;
pipeline_desc.depthStencil = &depth_stencil;
diff --git a/src/tests/3d/test_3d_render.cc b/src/tests/3d/test_3d_render.cc
index de9718e..ef799ec 100644
--- a/src/tests/3d/test_3d_render.cc
+++ b/src/tests/3d/test_3d_render.cc
@@ -140,6 +140,7 @@ int main(int argc, char** argv) {
InitShaderComposer();
+ g_renderer.set_direct_render(true); // Renders to surface, no post-process flip
g_renderer.init(g_device, g_queue, g_format);
g_renderer.resize(platform_state.width, platform_state.height);