-
Notifications
You must be signed in to change notification settings - Fork 0
[Batch 4] Separate water render pass + planar reflection #386
Copy link
Copy link
Open
Labels
batch-4Batch 4: Advanced GPUBatch 4: Advanced GPUdocumentationImprovements or additions to documentationImprovements or additions to documentationengineenhancementNew feature or requestNew feature or requestshaders
Description
Summary
Split water rendering into its own sub-pass after the opaque pass, with planar reflection texture. Currently water is rendered in the same drawOffset() loop as solid/cutout blocks with flat tinted color. This produces a visually flat appearance.
Depends on: #371 (MDI — avoids render loop conflicts)
Current Behavior
Water blocks are meshed in the fluid pass by chunk_mesh.zig. In WorldRenderer.render(), fluid allocations are drawn in the same loop as solid/cutout using the same terrain pipeline and shaders. The fragment shader applies a flat blue tint. There is no reflection, refraction, or animated normals.
Target Behavior
- Opaque pass renders all solid + cutout geometry (no water)
- Water reflection pass: re-render scene from reflected camera into texture
- Water pass: render water blocks using reflection texture + depth comparison for refraction
- Post-processing continues as normal
Implementation Plan
Step 1: Reflection texture
- Create offscreen render target:
VK_FORMAT_R8G8B8A8_SRGBcolor +VK_FORMAT_D32_SFLOATdepth - Resolution: half screen resolution (performance trade-off)
- Attach to frame resources, recreated on swapchain resize
Step 2: Reflection camera
- Mirror the main camera position across the water surface plane (y = water_level)
- Flip the view matrix:
reflect_view = scale(1, -1, 1) * view - Use a user-defined clip plane at y = water_level to prevent geometry below water from rendering
Step 3: Reflection render pass
- New render pass in
render_graph.zig:WaterReflectionPass - Renders the same scene (opaque + cutout only, no fluids) from reflected camera
- Outputs: reflection color texture
- Optimization: only render chunks near water (within reflection influence distance)
- Optimization: render at half resolution
Step 4: Water render pass
- New render pass in
render_graph.zig:WaterPass - Inputs: scene depth buffer, reflection texture, water geometry
- Water fragment shader samples reflection texture with reflected UV
- Depth comparison: pixels behind water surface get refraction tint
- Add per-pixel depth-based alpha: shallow water is clearer, deep water is opaque
Step 5: Integration
WorldRenderer.render()split:- First pass: draw solid + cutout (skip fluid)
- Reflection pass: draw solid + cutout with reflected camera
- Water pass: draw fluid blocks with reflection texture
- Render order managed by
RenderGraph
Files to Create
src/engine/graphics/vulkan/water_system.zig— reflection texture, water pipelineassets/shaders/vulkan/water.vert— water vertex shaderassets/shaders/vulkan/water.frag— water fragment shader with reflectionassets/shaders/vulkan/water.vert.spv+water.frag.spv
Files to Modify
src/engine/graphics/render_graph.zig— add WaterReflectionPass and WaterPasssrc/world/world_renderer.zig— separate fluid rendering from solid/cutoutsrc/engine/graphics/vulkan/frame_manager.zig— reflection texture resourcessrc/engine/graphics/vulkan/pipeline_manager.zig— water pipelinebuild.zig— glslangValidator checks for water shaders
Testing
- Water reflects the sky and terrain above it
- Reflection updates when camera moves
- No rendering artifacts at water edges
- Performance impact measurable and acceptable (<2ms for reflection pass)
- Water still renders without reflection on LOW preset (fallback)
- Depth-based color absorption visible (shallow = clear, deep = opaque)
- Works with TAA (no flickering)
Roadmap: docs/PERFORMANCE_ROADMAP.md — Batch 4, Issue 4C-1
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
batch-4Batch 4: Advanced GPUBatch 4: Advanced GPUdocumentationImprovements or additions to documentationImprovements or additions to documentationengineenhancementNew feature or requestNew feature or requestshaders