-
Notifications
You must be signed in to change notification settings - Fork 0
[Batch 5] Water shader: Fresnel, animated normals, depth absorption #390
Copy link
Copy link
Open
Labels
batch-5Batch 5: Final PushBatch 5: Final PushdocumentationImprovements or additions to documentationImprovements or additions to documentationenhancementNew feature or requestNew feature or requesthotfixquestionFurther information is requestedFurther information is requestedshaders
Description
Summary
Improve the water fragment shader with physically-based rendering: Fresnel reflection/refraction blending, animated normal maps for wave simulation, and depth-based color absorption. This builds on the separate water render pass from #386.
Depends on: #386 (water render pass + reflection texture)
Current State (after #386)
Water has a reflection texture and a basic water fragment shader. The shader samples the reflection texture but lacks:
- Fresnel effect (reflection stronger at grazing angles)
- Surface animation (static flat water)
- Depth-based coloring (uniform blue regardless of depth)
Target Effects
1. Fresnel Reflection/Refraction
float fresnel = schlickFresnel(dot(view_dir, normal), F0);
vec3 color = mix(refraction_color, reflection_color, fresnel);F0for water ≈ 0.02 (dielectric)- Looking straight down → mostly refraction (see through)
- Looking at grazing angle → mostly reflection (mirror-like)
- Creates natural-looking water at all viewing angles
2. Animated Normal Maps
Two approaches (pick one):
Option A: Scrolling normal maps
- Tile a normal map texture across the water surface
- Scroll UV over time (two layers at different speeds/directions for complexity)
- Simple and effective, used in most games
Option B: Gerstner waves (procedural)
- Compute wave normal procedurally from sum of sine waves
- Parameters: wavelength, amplitude, direction, speed
- More realistic but more GPU cost
- Recommended for a tech showcase engine
Recommendation: Option A for now (simpler, proven), with Option B as a future enhancement.
3. Depth-Based Color Absorption
float water_depth = scene_depth - surface_depth;
vec3 shallow_color = vec3(0.1, 0.6, 0.8); // light blue
vec3 deep_color = vec3(0.02, 0.05, 0.15); // dark navy
vec3 absorption = mix(shallow_color, deep_color, clamp(water_depth / max_depth, 0, 1));- Compare water surface depth with scene depth buffer
- Shallow water (depth < 1 block): nearly transparent, see through clearly
- Medium depth (3-5 blocks): blue tint with reduced visibility
- Deep water (10+ blocks): dark navy, opaque
4. Specular Highlights
vec3 specular = pow(max(dot(half_vec, wave_normal), 0.0), 128) * sun_color * sun_intensity;- Sun specular reflection on water surface
- Sharp highlight using high exponent (128)
- Only when sun is visible (not behind terrain)
Implementation Plan
Step 1: Fresnel effect
- Add view direction calculation in fragment shader
- Implement Schlick's Fresnel approximation
- Blend between reflection texture (from [Batch 4] Separate water render pass + planar reflection #386) and refracted scene color
Step 2: Animated normals
- Add a normal map texture to the texture atlas (or separate texture)
- Two scrolling layers:
normal = normalize(layer1 + layer2) - Time uniform from push constants or UBO
- Scroll speed configurable in settings
Step 3: Depth absorption
- Read scene depth from G-pass depth buffer (or depth attachment)
- Compare with interpolated fragment depth
- Apply exponential absorption curve
Step 4: Specular
- Sun direction from atmosphere system
- View direction from camera
- Wave normal from animated normal map
- Add specular contribution to final color
Step 5: Settings integration
- Water quality setting: LOW (flat tint), MEDIUM (reflection only), HIGH (all effects)
- Animated normals toggle
- Water color customization (future)
Files to Modify
assets/shaders/vulkan/water.frag— all shader effectsassets/shaders/vulkan/water.vert— pass time, wave parameterssrc/engine/graphics/vulkan/water_system.zig— normal map texture, time uniformsrc/engine/graphics/texture_atlas.zig— add water normal map slotsrc/game/settings/data.zig— water quality setting
Testing
- Fresnel effect visible: looking down = clear, looking across = reflective
- Water surface animates smoothly (no jitter)
- Shallow water is nearly transparent, deep water is opaque blue
- Sun creates specular highlight on water surface
- LOW preset falls back to flat tinted water
- TAA doesn't cause water flickering
- No performance regression > 1ms for water pass
Roadmap: docs/PERFORMANCE_ROADMAP.md — Batch 5, Issue 4C-2
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
batch-5Batch 5: Final PushBatch 5: Final PushdocumentationImprovements or additions to documentationImprovements or additions to documentationenhancementNew feature or requestNew feature or requesthotfixquestionFurther information is requestedFurther information is requestedshaders