#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);
}