#ifdef GL_ES
precision mediump float;
#endif

// Project Name : Azure Abyss (Aoi Naraku in Japanese)
// [Note] Please move your mouse !

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

vec2 ScreenToCentroid(vec2 coord)
{
       vec2 normalizedCoord = (coord / resolution.xy);
       vec2 centroidCoord = normalizedCoord - vec2(0.5);
       return centroidCoord;
}

vec2 CorrectAspect(vec2 coord)
{
       float aspect = resolution.y/resolution.x;
       return vec2(coord.x / aspect, coord.y);
}


float Deg2Rad(float deg)
{
       return 3.14159265358979 / 180.0 * deg;
}

// http://qiita.com/shimacpyon/items/d15dee44a0b8b3883f76
float rand(vec2 co){
   return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}


// http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
vec3 hsv2rgb(vec3 c)
{
   vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
   vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
   return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

vec4 DrawPoint(vec2 fragPos, vec2 centerPos, vec2 holePos, float baseRadius, vec2 hue)
{
       vec4 color;
       float fromCenter = length(fragPos - centerPos);
       float fromHole = length(fragPos - holePos);
       float radius = baseRadius * (fromHole/2.0+0.5);
       float pointRegion = step(fromCenter, radius);
       color.rgb = hsv2rgb(vec3(mix(hue.x, hue.y, fromCenter/radius), 1.0-fromCenter, mix(0.0, 2.0, fromHole-0.1))) * pointRegion;
       float ghostEffect = 0.05;
       color.a = 1.0 - smoothstep(0.0, radius, fromCenter)+ghostEffect;
       return color;
}

void main( void ) {
       const int numBall = 12;
       vec2 initPos[numBall];
       vec2 initHue[numBall];

       float interval = 1.0;
       float tm = mod(time, interval)/interval;
       float timeChange = Deg2Rad(90.0 * (time/interval));
       float smoothValue = abs(sin(timeChange)); // 0 -> 1 -> 0 -> 1 -> 0 -> ...

       float deltaAngle = 360.0 / float(numBall);
       float ballRotateSpeed = 20.0;
       float deltaHue = 1.0 / float(numBall+1);
       for (int i = 0 ; i < numBall ; i++ ){
               float fi = float(i);
               float changeInitialAngleFactor = float(time) * ballRotateSpeed;
               float angle = Deg2Rad(float(i) * deltaAngle + changeInitialAngleFactor);
               vec2 dir = vec2(cos(angle), sin(angle)) * (0.5 + rand(vec2(fi,fi)));
               float xx = dir.x;
               float yy = dir.y;
               initPos[i] = CorrectAspect(vec2(xx, yy));
               initHue[i].x = deltaHue * float(i+1);
               initHue[i].y = deltaHue * float(i);
       }

       vec2 p = ScreenToCentroid(gl_FragCoord.xy);
       p = CorrectAspect(p);

       vec2 center = mouse- vec2(0.5); //mouse coord : leftdown=(0,0), rightup=(1,1)
       center = CorrectAspect(center);

       float radius = 0.25;
       float fromCenter = length(p - center);
       float toCenterBlack = fromCenter/radius;
       float frequency = 60.0;
       float speed = 3.0;
       float ringPower = 0.7;
       float blueHole = abs(sin(fromCenter*frequency + timeChange*speed)) * toCenterBlack * ringPower;
       blueHole *= rand(gl_FragCoord.xy * smoothValue);

       float ballMoveInterval = 3.0;
       int tt = int(time/ballMoveInterval);
       tt = int(mod(float(tt),float(numBall)));

       vec4 ballColor;
       for (int i = 0 ; i < numBall; i++ ){
               float ballMoveTm = mod(time + float(i), ballMoveInterval)/ballMoveInterval;
               vec2 ballPos = mix(initPos[i], center, ballMoveTm);
               vec4 ret = DrawPoint(p, ballPos, center, 0.05, initHue[i]);
               ballColor += ret;
       }

       gl_FragColor = vec4(ballColor.r * ballColor.a, ballColor.g * ballColor.a, ballColor.b * ballColor.a + blueHole * 1.5 * (1.0-ballColor.a), 1.0);
}