1// Source: Android Open Source Project 2// https://cs.android.com/android/_/android/platform/frameworks/base/+/main:graphics/java/android/graphics/drawable/RippleShader.java 3 4uniform vec2 in_origin; 5uniform vec2 in_touch; 6uniform float in_progress; 7uniform float in_maxRadius; 8uniform vec2 in_resolutionScale; 9uniform vec2 in_noiseScale; 10uniform float in_hasMask; 11uniform float in_noisePhase; 12uniform float in_turbulencePhase; 13uniform vec2 in_tCircle1; 14uniform vec2 in_tCircle2; 15uniform vec2 in_tCircle3; 16uniform vec2 in_tRotation1; 17uniform vec2 in_tRotation2; 18uniform vec2 in_tRotation3; 19layout(color) uniform vec4 in_color; 20layout(color) uniform vec4 in_sparkleColor; 21uniform shader in_shader; 22 23float triangleNoise(vec2 n) { 24 n = fract(n * vec2(5.3987, 5.4421)); 25 n += dot(n.yx, n.xy + vec2(21.5351, 14.3137)); 26 float xy = n.x * n.y; 27 return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0; 28} 29const float PI = 3.1415926535897932384626; 30float threshold(float v, float l, float h) { 31 return step(l, v) * (1.0 - step(h, v)); 32} 33float sparkles(vec2 uv, float t) { 34 float n = triangleNoise(uv); 35 float s = 0.0; 36 for (float i = 0; i < 4; i += 1) { 37 float l = i * 0.1; 38 float h = l + 0.05; 39 float o = sin(PI * (t + 0.35 * i)); 40 s += threshold(n + o, l, h); 41 } 42 return saturate(s) * in_sparkleColor.a; 43} 44float softCircle(vec2 uv, vec2 xy, float radius, float blur) { 45 float blurHalf = blur * 0.5; 46 float d = distance(uv, xy); 47 return 1. - smoothstep(1. - blurHalf, 1. + blurHalf, d / radius); 48} 49float softRing(vec2 uv, vec2 xy, float radius, float progress, float blur) { 50 float thickness = 0.05 * radius; 51 float currentRadius = radius * progress; 52 float circle_outer = softCircle(uv, xy, currentRadius + thickness, blur); 53 float circle_inner = softCircle(uv, xy, max(currentRadius - thickness, 0.), 54 blur); 55 return saturate(circle_outer - circle_inner); 56} 57float subProgress(float start, float end, float progress) { 58 float sub = clamp(progress, start, end); 59 return (sub - start) / (end - start); 60} 61mat2 rotate2d(vec2 rad){ 62 return mat2(rad.x, -rad.y, rad.y, rad.x); 63} 64float circle_grid(vec2 resolution, vec2 coord, float time, vec2 center, 65 vec2 rotation, float cell_diameter) { 66 coord = rotate2d(rotation) * (center - coord) + center; 67 coord = mod(coord, cell_diameter) / resolution; 68 float normal_radius = cell_diameter / resolution.y * 0.5; 69 float radius = 0.65 * normal_radius; 70 return softCircle(coord, vec2(normal_radius), radius, radius * 50.0); 71} 72float turbulence(vec2 uv, float t) { 73 const vec2 scale = vec2(0.8); 74 uv = uv * scale; 75 float g1 = circle_grid(scale, uv, t, in_tCircle1, in_tRotation1, 0.17); 76 float g2 = circle_grid(scale, uv, t, in_tCircle2, in_tRotation2, 0.2); 77 float g3 = circle_grid(scale, uv, t, in_tCircle3, in_tRotation3, 0.275); 78 float v = (g1 * g1 + g2 - g3) * 0.5; 79 return saturate(0.45 + 0.8 * v); 80} 81 82vec4 main(vec2 p) { 83 float fadeIn = subProgress(0., 0.13, in_progress); 84 float scaleIn = subProgress(0., 1.0, in_progress); 85 float fadeOutNoise = subProgress(0.4, 0.5, in_progress); 86 float fadeOutRipple = subProgress(0.4, 1., in_progress); 87 vec2 center = mix(in_touch, in_origin, saturate(in_progress * 2.0)); 88 float ring = softRing(p, center, in_maxRadius, scaleIn, 1.); 89 float alpha = min(fadeIn, 1. - fadeOutNoise); 90 vec2 uv = p * in_resolutionScale; 91 vec2 densityUv = uv - mod(uv, in_noiseScale); 92 float turbulence = turbulence(uv, in_turbulencePhase); 93 float sparkleAlpha = sparkles(densityUv, in_noisePhase) * ring * alpha * turbulence; 94 float fade = min(fadeIn, 1. - fadeOutRipple); 95 float waveAlpha = softCircle(p, center, in_maxRadius * scaleIn, 1.) * fade * in_color.a; 96 vec4 waveColor = vec4(in_color.rgb * waveAlpha, waveAlpha); 97 vec4 sparkleColor = vec4(in_sparkleColor.rgb * in_sparkleColor.a, in_sparkleColor.a); 98 float mask = in_hasMask == 1. ? in_shader.eval(p).a > 0. ? 1. : 0. : 1.; 99 return mix(waveColor, sparkleColor, sparkleAlpha) * mask; 100} 101