Constant RIPPLE_WGSL
Source pub const RIPPLE_WGSL: &str = "struct Drops {\n head: vec4<f32>,\n items: array<vec4<f32>, 8>,\n}\n\n@group(0) @binding(0) var water_prev: texture_2d<f32>;\n@group(0) @binding(1) var water_next: texture_storage_2d<rgba16float, write>;\n@group(0) @binding(2) var<uniform> drops: Drops;\n\nfn height_at(c: vec2<i32>, dims: vec2<i32>) -> f32 {\n return textureLoad(water_prev, clamp(c, vec2<i32>(0), dims - vec2<i32>(1)), 0).r;\n}\n\n@compute @workgroup_size(8, 8)\nfn ripple(@builtin(global_invocation_id) id: vec3<u32>) {\n let dims = vec2<i32>(textureDimensions(water_prev));\n let c = vec2<i32>(id.xy);\n if (any(c >= dims)) {\n return;\n }\n let here = textureLoad(water_prev, c, 0);\n let around = height_at(c + vec2<i32>(-1, 0), dims)\n + height_at(c + vec2<i32>(1, 0), dims)\n + height_at(c + vec2<i32>(0, -1), dims)\n + height_at(c + vec2<i32>(0, 1), dims);\n var h = (around * 0.5 - here.g) * 0.991;\n let uv = (vec2<f32>(c) + 0.5) / vec2<f32>(dims);\n let aspect = vec2<f32>(f32(dims.x) / f32(dims.y), 1.0);\n let count = u32(drops.head.x);\n for (var i = 0u; i < count; i++) {\n let d = drops.items[i];\n let q = (uv - d.xy) * aspect / max(d.z, 1e-4);\n h += d.w * exp(-dot(q, q));\n }\n textureStore(water_next, c, vec4<f32>(h, here.r, 0.0, 1.0));\n}\n";