blob: adc410c776c1b3afaf89fbe73e4da41576378b50 [file] [log] [blame]
#version 320 es
// Copyright 2013 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;
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 saturate(float x) {
return clamp(x, 0.0, 1.0);
}
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 saturate(circle_outer - circle_inner);
}
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 saturate(s) * 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 saturate(0.45 + 0.8 * v);
}
void main() {
vec2 p = gl_FragCoord.xy;
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);
}