material-ui-rs 0.5.3

A Material3 inspired theme for `iced`
Documentation
struct RippleUniforms {
    physical: vec4<f32>,
    resolution: vec4<f32>,
    touch_origin: vec4<f32>,
    progress_radius: vec4<f32>,
    color: vec4<f32>,
    sparkle_color: vec4<f32>,
    circle12: vec4<f32>,
    circle3_rotation1: vec4<f32>,
    rotation23: vec4<f32>,
    clip_radius: vec4<f32>,
}

@group(0) @binding(0)
var<uniform> uniforms: RippleUniforms;

struct VertexOutput {
    @builtin(position) position: vec4<f32>,
}

@vertex
fn vs_main(@builtin(vertex_index) vertex_index: u32) -> VertexOutput {
    var positions = array<vec2<f32>, 3>(
        vec2<f32>(-1.0, -1.0),
        vec2<f32>(3.0, -1.0),
        vec2<f32>(-1.0, 3.0),
    );

    var output: VertexOutput;
    output.position = vec4<f32>(positions[vertex_index], 0.0, 1.0);
    return output;
}

const PI: f32 = 3.1415926535897932384626;

fn saturate(value: f32) -> f32 {
    return clamp(value, 0.0, 1.0);
}

fn mod2(value: vec2<f32>, divisor: vec2<f32>) -> vec2<f32> {
    return value - divisor * floor(value / divisor);
}

fn threshold(value: f32, low: f32, high: f32) -> f32 {
    if value >= low && value < high {
        return 1.0;
    }

    return 0.0;
}

fn triangle_noise(n: vec2<f32>) -> f32 {
    var point = fract(n * vec2<f32>(5.3987, 5.4421));
    let offset = dot(point.yx, point.xy + vec2<f32>(21.5351, 14.3137));
    point = point + vec2<f32>(offset);

    let xy = point.x * point.y;
    return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0;
}

fn sparkles(uv: vec2<f32>, time: f32, sparkle_alpha: f32) -> f32 {
    let noise = triangle_noise(uv);
    var sparkle = 0.0;

    for (var index = 0u; index < 4u; index = index + 1u) {
        let i = f32(index);
        let low = i * 0.1;
        let high = low + 0.05;
        let offset = sin(PI * (time + 0.35 * i));

        sparkle = sparkle + threshold(noise + offset, low, high);
    }

    return saturate(sparkle) * sparkle_alpha;
}

fn sub_progress(start: f32, end: f32, progress: f32) -> f32 {
    let sub = clamp(progress, start, end);
    return (sub - start) / (end - start);
}

fn soft_circle(point: vec2<f32>, center: vec2<f32>, radius: f32, blur: f32) -> f32 {
    if radius <= 0.0 {
        return 0.0;
    }

    let blur_half = blur * 0.5;
    let dist = distance(point, center);

    return 1.0 - smoothstep(1.0 - blur_half, 1.0 + blur_half, dist / radius);
}

fn soft_ring(point: vec2<f32>, center: vec2<f32>, radius: f32, progress: f32, blur: f32) -> f32 {
    let thickness = 0.05 * radius;
    let current_radius = radius * progress;
    let outer = soft_circle(point, center, current_radius + thickness, blur);
    let inner = soft_circle(point, center, max(current_radius - thickness, 0.0), blur);

    return saturate(outer - inner);
}

fn rotate2d(rotation: vec2<f32>, delta: vec2<f32>) -> vec2<f32> {
    let matrix = mat2x2<f32>(
        vec2<f32>(rotation.x, -rotation.y),
        vec2<f32>(rotation.y, rotation.x),
    );

    return matrix * delta;
}

fn circle_grid(
    resolution: vec2<f32>,
    coord: vec2<f32>,
    center: vec2<f32>,
    rotation: vec2<f32>,
    cell_diameter: f32,
) -> f32 {
    let rotated = rotate2d(rotation, center - coord) + center;
    let cell = mod2(rotated, vec2<f32>(cell_diameter)) / resolution;
    let normal_radius = cell_diameter / resolution.y * 0.5;
    let radius = 0.65 * normal_radius;

    return soft_circle(
        cell,
        vec2<f32>(normal_radius),
        radius,
        radius * 50.0,
    );
}

fn turbulence(uv: vec2<f32>) -> f32 {
    let scale = vec2<f32>(0.8);
    let scaled_uv = uv * scale;
    let circle1 = uniforms.circle12.xy;
    let circle2 = uniforms.circle12.zw;
    let circle3 = uniforms.circle3_rotation1.xy;
    let rotation1 = uniforms.circle3_rotation1.zw;
    let rotation2 = uniforms.rotation23.xy;
    let rotation3 = uniforms.rotation23.zw;
    let grid1 = circle_grid(scale, scaled_uv, circle1, rotation1, 0.17);
    let grid2 = circle_grid(scale, scaled_uv, circle2, rotation2, 0.2);
    let grid3 = circle_grid(scale, scaled_uv, circle3, rotation3, 0.275);
    let value = (grid1 * grid1 + grid2 - grid3) * 0.5;

    return saturate(0.45 + 0.8 * value);
}

fn corner_mask(point: vec2<f32>, center: vec2<f32>, radius: f32) -> f32 {
    if radius <= 0.0 || distance(point, center) <= radius {
        return 1.0;
    }

    return 0.0;
}

fn rounded_rect_mask(point: vec2<f32>, size: vec2<f32>) -> f32 {
    if uniforms.physical.w < 0.5 {
        return 1.0;
    }

    if point.x < 0.0 || point.y < 0.0 || point.x > size.x || point.y > size.y {
        return 0.0;
    }

    let max_radius = min(size.x, size.y) * 0.5;
    let top_left = clamp(uniforms.clip_radius.x, 0.0, max_radius);
    let top_right = clamp(uniforms.clip_radius.y, 0.0, max_radius);
    let bottom_right = clamp(uniforms.clip_radius.z, 0.0, max_radius);
    let bottom_left = clamp(uniforms.clip_radius.w, 0.0, max_radius);

    if point.x < top_left && point.y < top_left {
        return corner_mask(point, vec2<f32>(top_left, top_left), top_left);
    }

    if point.x > size.x - top_right && point.y < top_right {
        return corner_mask(point, vec2<f32>(size.x - top_right, top_right), top_right);
    }

    if point.x > size.x - bottom_right && point.y > size.y - bottom_right {
        return corner_mask(
            point,
            vec2<f32>(size.x - bottom_right, size.y - bottom_right),
            bottom_right,
        );
    }

    if point.x < bottom_left && point.y > size.y - bottom_left {
        return corner_mask(point, vec2<f32>(bottom_left, size.y - bottom_left), bottom_left);
    }

    return 1.0;
}

@fragment
fn fs_main(@builtin(position) position: vec4<f32>) -> @location(0) vec4<f32> {
    let scale_factor = uniforms.physical.z;
    let point = (position.xy - uniforms.physical.xy) / scale_factor;
    let size = uniforms.resolution.xy;
    let progress = uniforms.progress_radius.x;
    let max_radius = uniforms.progress_radius.y;
    let noise_phase = uniforms.progress_radius.z;
    let fade_in = sub_progress(0.0, 0.13, progress);
    let scale_in = sub_progress(0.0, 1.0, progress);
    let fade_out_noise = sub_progress(0.4, 0.5, progress);
    let fade_out_ripple = sub_progress(0.4, 1.0, progress);
    let touch = uniforms.touch_origin.xy;
    let origin = uniforms.touch_origin.zw;
    let center = mix(touch, origin, saturate(progress * 2.0));
    let ring = soft_ring(point, center, max_radius, scale_in, 1.0);
    let alpha = min(fade_in, 1.0 - fade_out_noise);
    let uv = point / size;
    let density_uv = uv - mod2(uv, uniforms.resolution.zw);
    let turb = turbulence(uv);
    let sparkle_alpha =
        sparkles(density_uv, noise_phase, uniforms.sparkle_color.a) * ring * alpha * turb;
    let fade = min(fade_in, 1.0 - fade_out_ripple);
    let wave_alpha =
        soft_circle(point, center, max_radius * scale_in, 1.0) * fade * uniforms.color.a;
    let wave_color = vec4<f32>(uniforms.color.rgb * wave_alpha, wave_alpha);
    let sparkle_color = vec4<f32>(
        uniforms.sparkle_color.rgb * uniforms.sparkle_color.a,
        uniforms.sparkle_color.a,
    );
    let mask = rounded_rect_mask(point, size);

    return mix(wave_color, sparkle_color, sparkle_alpha) * mask;
}