#version 330 core

in vec2 vTexCoord;

uniform float uTime;
uniform vec2 uResolution;
uniform vec2 uMouse;

uniform sampler2D uTextureUnit;
uniform vec4 uColor;
uniform float uDepth;

out vec4 fragColor;
out float gl_FragDepth;

#ifdef GL_ES
precision mediump float;
#endif

// emulate ShaderToy
#define iTime uTime
#define iResolution uResolution
#define iMouse uMouse

// emulate a black texture
#define texture(s, uv) vec4(0.0)

float tanh(float x) {
    float ex = exp(2.0 * x);
    return ((ex - 1.) / (ex + 1.));
}

vec3 tanh(vec3 x) {
    vec3 ex = exp(2.0 * x);
    return ((ex - 1.) / (ex + 1.));
}

// --------[ Original ShaderToy begins here ]---------- //

float line( vec2 p, vec2 a, vec2 b, float r) {                       // draw line a-b width r
    p -= a; b -= a;
    float d = length( p - b * clamp(dot(p,b)/dot(b,b), 0., 1. ));
    return  smoothstep(1.,.0, d/r);
}

void mainImage( out vec4 O, vec2 U ) {
    O -= O; 
    vec2 R = iResolution.xy, U0 = U/R.y, U1;
    if (abs(U0.x-.5*R.x/R.y) > .35) return;                          // margins
    
    float N = 10./2.,                                                // number of cells/birds vertically
          Y, k = .1,                                                 // flight acceleration
        t = iTime/5., ft = fract(t),  tb = 1.5*iTime,                // beat vs scroll cycles
        pix = N / R.y;                                               // pixel size
    U *= pix; U.y *= 1.8;
    pix = N/360.;                                                    // lines thickness
    U.y -= 3.;                                                       // trigger height 
    if (U.y>0.) U.x -= .02*U.y*U.y;                                  // flight to right (distorted)
    U1 = U;
    U.y -= ft;                                                       // scrolled scaled coordinates

    for (int i=0; i<2; i++)		                            // odd / even columns
    {
        vec2 P = floor(U), V = fract(U)-.5;
        if (U1.y>0.) {                                                // flying acceleration 
           Y = log(1.+k*(U1.y-1.))/k - ft;            // inv(Y) = (exp(k*Y)-1.)/k + 1.
           if (Y>-.5) {
              P.y = ceil(Y); 
              V.y =  ( exp(k*Y) - exp(k*(P.y-.5)) ) / k // pseudofrac = ( inv(Y) - inv(center) )       
                    * exp(k*ft);                        //             / jacobian( inv(Y) )
            }}
                                                                   
        float rnd = P.x*111.7 + (P.y-floor(t))*71.3 + float(i)*74.3, // random phase for bird cycle
                h = mix(1., cos(tb+rnd), clamp(U1.y/5.,0.,1.));      // flying beat
        
        for( float s=-1.; s<2.; s+=2. )                              // left / right wing
        {
            float a = 1./.1, x = a*V.x, y,                         
                  b = 1.-clamp(U1.y/7.,0.,1.);                       // body shrinking
            O += line( V, vec2(.1*b*s,0), vec2(.4*s,-.5*h), 2.*pix)  // wing itself
                 ; // * sin(P.y-floor(t)+vec4(0,2.1,-2.1,0));            // wing Id, for debug
            if (abs(x) < b) {                                        // (half) body
                y = fract(x-.25-b); y = min(y,1.-y)*2.-.5;
                x = floor(x);
                O += line( V, vec2(x,y*s*h)/a, vec2(x+1.,y*s*h)/a, 4.*pix);
            }
        }
        U+=.5; U1+=.5;
    }
    
  //O = .9*(1.-O) - max(0., texture(iChannel0,U0).x-U0.y*2.);        // background 
    O = .9 
        - O*vec4(1,1,mix(1.,.5, sqrt(U0.y)),0)                       // wire 
        - max(0., texture(iChannel0,U0).x-U0.y*2.)*vec4(1,.9,1,0);   // grass
}

// --------[ Original ShaderToy ends here ]---------- //

void main(void)
{
    mainImage(fragColor, vec2(vTexCoord.x, 1.0 - vTexCoord.y) * uResolution);

    fragColor *= uColor;
    gl_FragDepth = uDepth;
}
