#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 resolution;
uniform float time;
uniform sampler2D backbuffer;

float distanceFunction(vec3 p)
{
       float repeat = 0.8+.2*sin(time);
       //all
       vec3 allPos = vec3(sin(time),sin(time),-1.5*time);
       //tor
       vec3 torPos = p + vec3( 0.0+ 0.375* sin(time),-1.49,0.0)+allPos;
       //torPos = mod(vec3(p.x,p.y,p.z),1.0);
       //vec3 torPos = p;
       torPos = mod(torPos, repeat)-repeat/2.0;
       vec2 t = vec2( 0.75,0.749);
       vec2 q = vec2(length(torPos.xz)-t.x,torPos.y);
       float d2 = length(q)-t.y;

       //sp

       vec3 spPos = p + vec3( 0.0,-0.77,0.0)+allPos;
       spPos = mod(spPos, repeat)-repeat/2.0;
       float d1 =length(spPos) - 0.8;
       return max(-d2,d1);

       //return d2;
}


vec3 getNormal(vec3 p)
{
 const float d = 0.0001;
 return
   normalize
   (
     vec3
     (
       distanceFunction(p+vec3(d,0.0,0.0))-distanceFunction(p+vec3(-d,0.0,0.0)),
       distanceFunction(p+vec3(0.0,d,0.0))-distanceFunction(p+vec3(0.0,-d,0.0)),
       distanceFunction(p+vec3(0.0,0.0,d))-distanceFunction(p+vec3(0.0,0.0,-d))
     )
   );
}
const vec3 alb =vec3(1.5,0.5,1.2);
//const vec3 amb =vec3(0.2,0.45,0.38);
const vec3 amb =vec3(0.,0.45,0.38);
const vec3 sp=vec3(2.5,1.0,1.25);
void main() {
 vec2 pos = (gl_FragCoord.xy*2.0 -resolution) / resolution.y;

 vec3 camPos = vec3(0.0, 1.4, 3.0);
 vec3 camDir = normalize( vec3(cos(time), -0.5*sin(time), -1.0) );
 vec3 camUp = vec3(0.0, 1.0, 0.0);
 vec3 camSide = cross(camDir, camUp);
vec3 lightDir = vec3(0.1,0.2,-0.5);
 float focus = 1.8;

 vec3 rayDir = normalize(camSide*pos.x + camUp*pos.y + camDir*focus);

 float t = 0.0, d;
 vec3 posOnRay = camPos;

 for(int i=0; i<16; ++i)
 {
   d = distanceFunction(posOnRay);
   if((d)<0.001) break;
   t += d;
   posOnRay = camPos + t*rayDir;
 }

 vec4 blur = texture2D(backbuffer,gl_FragCoord.xy/resolution.xy);
 if(abs(d) < 0.1)
 {

   vec3 normal = getNormal(posOnRay);
         float diff = dot(lightDir,normal);
         vec3 halfVec = normalize(lightDir-camDir);
         float spec = pow(max(dot(normal, halfVec), 0.0),20.0);
         vec3 light = diff*vec3(1.0)+amb;
         gl_FragColor = vec4(alb*light+spec*sp,1.0)+0.2*blur;
         //gl_FragColor = blur;

 }else
 {
   gl_FragColor = vec4(0.01,0.0,0.05,1.0);
 }
}