#ifdef GL_ES
       precision mediump float;
#endif

uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;
uniform sampler2D backbuffer;

#define ITE_MAX      100
#define DIST_COEFF   1.00
#define DIST_MIN     0.01
#define DIST_MAX     2000.0

#define pi 3.14159265
float perlin(vec3 p) {
       vec3 i = floor(p);
       vec4 a = dot(i, vec3(1., 57., 21.)) + vec4(0., 57., 21., 78.);
       vec3 f = cos((p-i)*pi)*(-.5)+.5;
       a = mix(sin(cos(a)*a),sin(cos(1.+a)*(1.+a)), f.x);
       a.xy = mix(a.xz, a.yw, f.y);
       return mix(a.x, a.y, f.z);
}

float map_flat(vec3 p) {
       float t = DIST_MAX;
       float w = 0.0;

       w = 0.1 + dot(p, vec3(0.0, 1.0, 0.0));
       t = min(t, w);

       return t;
}

float map(vec3 p0) {
       vec3 p = p0;
       float t = DIST_MAX;
       float w = 0.0;
       float tt = mod(0.95 * time, 1.8) - 0.9;

       w = 0.6 * length(p + vec3(-0.4, -0.0 ,0.0) + 0.9 * sin(tt)) - 0.2  + 0.6 * sin(-tt - 1.2) * 0.3 * perlin(p * (tt - 0.81) * 60.0);
       t = min(t, w);

       return t;
}

float lambert(vec3 p) {
       vec3 light = normalize(vec3(0.0, 1.0,0.0));
       vec3 eye = normalize(vec3(0.0, 0.0, 1.0));
       vec3 pos = normalize(p);
       vec3 hv = normalize(light+ eye);
       float d = max(dot(pos,-hv), 0.0);
       return d;
}

float getDistance(float t, vec3 dir, vec3 eye){
   for(int i = 0 ; i < ITE_MAX; i++) {
       float ttemp = map(t * dir + eye);
       ttemp *= map_flat(t * dir + eye);
       if (ttemp < DIST_MIN)
           break;
           t += ttemp * DIST_COEFF;
   }
       return t;
}



void main( void ) {
       vec2 uv = ( gl_FragCoord.xy / resolution.xy ) * 2.0 - 1.0;

       float aspect = resolution.x / resolution.y;
       vec3  dir = normalize(vec3(uv * vec2(aspect, 1.0), 1.0));

       vec3 eye = vec3(mouse.x, mouse.y, -1.0);

       float t = 0.0;
       t = getDistance(t, dir, eye);

       vec3 ip = eye + dir * t;

       vec3 color = vec3(1.0,1.0,1.0);
       if (t < 1.8){
           color = vec3(t *0.3,t*0.3,t);
       }
       color = color * lambert(ip) ;


        //vec3 bg = vec3(uv.y * uv.y, 0.4,0.0);
        gl_FragColor = vec4(color, 1.0)+ 0.65* texture2D(backbuffer, gl_FragCoord.xy / resolution.xy);
}