#version 320 es // Copyright 2014 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. precision highp float; #include // TODO(antrob): Put these in a more logical order (e.g. separate consts vs varying, etc) layout(location = 0) uniform vec4 u_color; layout(location = 1) uniform float u_alpha; layout(location = 2) uniform vec4 u_sparkle_color; layout(location = 3) uniform float u_sparkle_alpha; layout(location = 4) uniform float u_blur; layout(location = 5) uniform vec2 u_center; layout(location = 6) uniform float u_radius_scale; layout(location = 7) uniform float u_max_radius; layout(location = 8) uniform vec2 u_resolution_scale; layout(location = 9) uniform vec2 u_noise_scale; layout(location = 10) uniform float u_noise_phase; layout(location = 11) uniform vec2 u_circle1; layout(location = 12) uniform vec2 u_circle2; layout(location = 13) uniform vec2 u_circle3; layout(location = 14) uniform vec2 u_rotation1; layout(location = 15) uniform vec2 u_rotation2; layout(location = 16) uniform vec2 u_rotation3; layout(location = 0) out vec4 fragColor; const float PI = 3.1415926535897932384626; const float PI_ROTATE_RIGHT = PI * 0.0078125; const float PI_ROTATE_LEFT = PI * -0.0078125; const float ONE_THIRD = 1./3.; const vec2 TURBULENCE_SCALE = vec2(0.8); float triangle_noise(highp vec2 n) { n = fract(n * vec2(5.3987, 5.4421)); n += dot(n.yx, n.xy + vec2(21.5351, 14.3137)); float xy = n.x * n.y; return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0; } float threshold(float v, float l, float h) { return step(l, v) * (1.0 - step(h, v)); } mat2 rotate2d(vec2 rad){ return mat2(rad.x, -rad.y, rad.y, rad.x); } float soft_circle(vec2 uv, vec2 xy, float radius, float blur) { float blur_half = blur * 0.5; float d = distance(uv, xy); return 1.0 - smoothstep(1.0 - blur_half, 1.0 + blur_half, d / radius); } float soft_ring(vec2 uv, vec2 xy, float radius, float thickness, float blur) { float circle_outer = soft_circle(uv, xy, radius + thickness, blur); float circle_inner = soft_circle(uv, xy, max(radius - thickness, 0.0), blur); return clamp(circle_outer - circle_inner, 0.0, 1.0); } float circle_grid(vec2 resolution, vec2 p, vec2 xy, vec2 rotation, float cell_diameter) { p = rotate2d(rotation) * (xy - p) + xy; p = mod(p, cell_diameter) / resolution; float cell_uv = cell_diameter / resolution.y * 0.5; float r = 0.65 * cell_uv; return soft_circle(p, vec2(cell_uv), r, r * 50.0); } float sparkle(vec2 uv, float t) { float n = triangle_noise(uv); float s = threshold(n, 0.0, 0.05); s += threshold(n + sin(PI * (t + 0.35)), 0.1, 0.15); s += threshold(n + sin(PI * (t + 0.7)), 0.2, 0.25); s += threshold(n + sin(PI * (t + 1.05)), 0.3, 0.35); return clamp(s, 0.0, 1.0) * 0.55; } float turbulence(vec2 uv) { vec2 uv_scale = uv * TURBULENCE_SCALE; float g1 = circle_grid(TURBULENCE_SCALE, uv_scale, u_circle1, u_rotation1, 0.17); float g2 = circle_grid(TURBULENCE_SCALE, uv_scale, u_circle2, u_rotation2, 0.2); float g3 = circle_grid(TURBULENCE_SCALE, uv_scale, u_circle3, u_rotation3, 0.275); float v = (g1 * g1 + g2 - g3) * 0.5; return clamp(0.45 + 0.8 * v, 0.0, 1.0); } void main() { vec2 p = FlutterFragCoord(); vec2 uv = p * u_resolution_scale; vec2 density_uv = uv - mod(p, u_noise_scale); float radius = u_max_radius * u_radius_scale; float turbulence = turbulence(uv); float ring = soft_ring(p, u_center, radius, 0.05 * u_max_radius, u_blur); float sparkle = sparkle(density_uv, u_noise_phase) * ring * turbulence * u_sparkle_alpha; float wave_alpha = soft_circle(p, u_center, radius, u_blur) * u_alpha * u_color.a; vec4 wave_color = vec4(u_color.rgb * wave_alpha, wave_alpha); vec4 sparkle_color = vec4(u_sparkle_color.rgb * u_sparkle_color.a, u_sparkle_color.a); fragColor = mix(wave_color, sparkle_color, sparkle); }