3#define_import_path aqua::shore::water 5#import aqua::cascade::{bed_height, cascade_layout, caustics_sampler, caustics_texture, surface} 9const NO_BED_DEPTH: f32 = 256.0; 11const CAUSTIC_CELLS_PER_TILE: f32 = 16.0; 13const CAUSTIC_FOCUS_GAIN: f32 = 12.0; 15const CAUSTIC_DAYLIGHT_MIN_LUX: f32 = 64.0; 16const CAUSTIC_REFERENCE_SUN_LUX: f32 = 120000.0; 17const CAUSTIC_LUMINANCE_WEIGHTS: vec3<f32> = vec3(0.2126, 0.7152, 0.0722); 26fn bed_water_depth(world_xz: vec2<f32>) -> f32 { 27 let range = cascade_layout.bed_range; 31 let uv = (world_xz - cascade_layout.bed_transform.xy) 32 * cascade_layout.bed_transform.zw; 33 if any(uv < vec2(0.0)) || any(uv > vec2(1.0)) { 36 let dimensions = vec2<f32>(textureDimensions(bed_height)); 37 let texel_position = uv * (dimensions - vec2(1.0)); 38 let base = vec2<i32>(floor(texel_position)); 39 let fraction = fract(texel_position); 40 let maximum = i32(dimensions.x) - 1; 41 let maximum_y = i32(dimensions.y) - 1; 42 let p00 = clamp(base, vec2(0), vec2(maximum, maximum_y)); 43 let p10 = clamp(base + vec2(1, 0), vec2(0), vec2(maximum, maximum_y)); 44 let p01 = clamp(base + vec2(0, 1), vec2(0), vec2(maximum, maximum_y)); 45 let p11 = clamp(base + vec2(1), vec2(0), vec2(maximum, maximum_y)); 47 textureLoad(bed_height, p00, 0).r, 48 textureLoad(bed_height, p10, 0).r, 52 textureLoad(bed_height, p01, 0).r, 53 textureLoad(bed_height, p11, 0).r, 56 let height = mix(row_0, row_1, fraction.y) * range.y + range.x; 57 return max(range.z - height, 0.0); 62fn blended_water_depth(world_xz: vec2<f32>) -> f32 { 63 return min(bed_water_depth(world_xz), surface.sea_floor.x); 67fn caustic_bed_radiance( 68 scene_colour: vec3<f32>, 72 sun_direction: vec3<f32>, 73 sun_unexposed_radiance: vec3<f32>, 75 extinction: vec3<f32>, 77 let strength = surface.caustics.x * surface.sea_floor.w; 81 let maximum_depth = surface.caustics.w; 82 if water_depth >= maximum_depth || sun_direction.y <= 0.0 || sun_shadow <= 0.0 { 85 let scale = surface.caustics.y * CAUSTIC_CELLS_PER_TILE; 86 let scroll = surface.caustics.z * time / scale; 88 let uv_a = world_xz / scale + vec2(scroll, 0.63 * scroll); 89 let uv_b = world_xz * 1.37 / scale + vec2(-0.71 * scroll, 0.43 * scroll); 90 let a = textureSampleLevel(caustics_texture, caustics_sampler, uv_a, 0.0).r; 91 let b = textureSampleLevel(caustics_texture, caustics_sampler, uv_b, 0.0).r; 92 let pattern = CAUSTIC_FOCUS_GAIN * a * b; 93 let depth_gate = 1.0 - smoothstep(0.0, maximum_depth, water_depth); 95 max(sun_unexposed_radiance, vec3(0.0)), 96 CAUSTIC_LUMINANCE_WEIGHTS, 99 (direct_lux - CAUSTIC_DAYLIGHT_MIN_LUX) 100 / (CAUSTIC_REFERENCE_SUN_LUX - CAUSTIC_DAYLIGHT_MIN_LUX), 106 let bed_incidence = max(sun_direction.y, 0.0); 107 let incoming_path = water_depth / max(bed_incidence, 0.02); 108 let incoming_transmission = exp(-extinction * incoming_path); 109 let sun_chroma = max(sun_unexposed_radiance, vec3(0.0)) 110 / max(direct_lux, CAUSTIC_DAYLIGHT_MIN_LUX); 113 let focus = strength * depth_gate * pattern * daylight 114 * bed_incidence * sun_shadow; 115 return scene_colour + scene_colour * sun_chroma 116 * incoming_transmission * focus;