#ifdef GL_ES
precision mediump float;
#endif

#extension GL_OES_standard_derivatives : enable

uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;

const float eps = 1e-3;
const float pi = 3.1415926535;
const vec3 z_up = vec3(0.0, 0.0, 1.0);


float rand(vec2 p) {
   return fract(sin(dot(p, vec2(12.9898, 4.1414))) * 43758.5453);
}

float rand(float n){return fract(sin(n) * 43758.5453123);}

float noise(float p){
       float fl = floor(p);
 float fc = fract(p);
       return mix(rand(fl), rand(fl + 1.0), fc);
}

float noise(vec2 n) {
       const vec2 d = vec2(0.0, 1.0);
 vec2 b = floor(n), f = smoothstep(vec2(0.0), vec2(1.0), fract(n));
       return mix(mix(rand(b), rand(b + d.yx), f.x), mix(rand(b + d.xy), rand(b + d.yy), f.x), f.y);
}

float mod2(float p, float a) {
   return p - a * floor(p / a);
}

vec2 mod2(vec2 p, vec2 a) {
   return vec2(mod2(p.x, a.x), mod2(p.y, a.y));
}

float sdf_circle(vec2 p, vec2 o, float r) {
   return length(p - o) - r;
}

float sdf_ring(vec2 p, float r, float lineWidth) {
   float outer = sdf_circle(p, vec2(0, 0), r + 0.5 * lineWidth);
   float inner = sdf_circle(p, vec2(0, 0), r - 0.5 * lineWidth);

   return max(-inner, outer);
}

float sdf(vec2 p) {
   return min(sdf_ring(p, 0.75, 0.175), sdf_ring(p, 0.35, 0.175));
}

float sake_displacement(vec2 p, vec2 p0) {
   float dist = length(p - p0);
   vec2 dir = normalize(p - p0);

   float k = 5.0;
   float omega = 20.0;
   float basewave = 0.5 * sin(k * dist - mod2(omega * time, 2.0 * pi)) + 0.5;
   float k2 = 22.0;
   float omega2 = 44.0;
   float subwave = 0.5 * sin(k2 * dist - mod2(omega2 * time, 2.0 * pi)) + 0.5;
   float k3 = 45.0;
   float omega3 = 90.0;
   float subwave2 = 0.5 * sin(k3 * dist - mod2(omega3 * time, 2.0 * pi)) + 0.5;

   basewave = 2.0 * pow(basewave, 4.0) + 0.3 * pow(subwave, 2.0) + 0.09 * subwave2;

   float amp = min(1.0 / sqrt(eps + dist), 1.0);
   amp *= basewave;

   float outer_r = 0.82;
   amp += 100.0 * step(outer_r, length(p)) * (length(p) - outer_r) * (length(p) - outer_r);

   amp = 1.0 - exp(-amp);

   amp *= step(length(p0), 0.85);

   return -0.1 * amp;
}

vec3 sake_normal(vec2 p, vec2 p0) {
   float dfx = sake_displacement(p + vec2(1.0, 0.0) * eps, p0) - sake_displacement(p - vec2(1.0, 0.0) * eps, p0);
   float dfy = sake_displacement(p + vec2(0.0, 1.0) * eps, p0) - sake_displacement(p - vec2(0.0, 1.0) * eps, p0);
   return normalize(vec3(dfx, dfy, 2.0 * eps));
}

void main( void )
{
   vec2 uv = (2.0 * gl_FragCoord.xy - resolution.xy) / resolution.xy;
   vec2 pos = (2.0 * gl_FragCoord.xy - resolution.xy) / min(resolution.x, resolution.y);
   vec2 mouse_pos = 2.0 * (mouse.xy - vec2(0.5));// min(resolution.x, resolution.y);
   mouse_pos.x *= resolution.x / resolution.y;

   vec3 light_dir = normalize(vec3(3.0, 2.0, 1.0));
   const float max_sake_depth = 0.4;
   // float sake_depth = max_sake_depth * mouse_pos.y;
   float sake_depth = max_sake_depth * (0.5 + 0.5 * sin(time));

   vec3 normal = sake_normal(pos, mouse_pos);
   vec3 refract_dir = refract(-z_up, normal, 1.4);

   vec2 displacement = refract_dir.xy / refract_dir.z * sake_depth;

   vec2 displaced_pos = pos + displacement;

   // rings
   vec3 ring_color = vec3(0.1, 0.1, 0.6);
   vec3 ring_edge_color = vec3(0.3, 0.6, 0.9);
   ring_color = mix(ring_edge_color, ring_color, smoothstep(-0.02, 0.02, -sdf(displaced_pos)));

   vec3 cup_color = vec3(0.98, 0.98, 0.98);
   vec3 color = mix(ring_color, cup_color, smoothstep(0.0, 0.02, sdf(displaced_pos)));

   color *= 1.0 - 1.0 * max(0.0, dot(displaced_pos, light_dir.xy));
   color *= mix(0.8, 1.0, sake_depth / max_sake_depth);
   color *= mix(vec3(1.0), vec3(1.0, 1.0, 0.0), 1.0 - exp(-0.1 * sake_depth));

   // reflection
   vec3 ref_dir = reflect(-z_up, normal);
   vec3 ref_color = 3.0 * vec3(1.0, 1.0, 1.0) * smoothstep(0.8, 0.9, dot(ref_dir, light_dir));
   ref_color += 0.5 * noise(2.0 * ref_dir.xy);
   ref_color *= 1.0 - exp(-2.0 * sake_depth);

   color += 1.0 * ref_color;

   // edge
   color = mix(color, cup_color * 0.6, smoothstep(0.86, 0.87, length(pos)));


   color = mix(color, vec3(0.1), smoothstep(0.91, 0.92, length(pos)));
   color *= 1.0 - 0.5 * length(uv) * length(uv);
   gl_FragColor = vec4(color, 1.0);
}