#define PI 3.14159265

vec3  rot(vec3 p,vec3 a,float t)
{
	a=normalize(a);
	return mix(a*dot(p,a),p,cos(t))+sin(t)*cross(p,a);
}



float map(vec3 p)
{
	p=rot(p,vec3(1,0,0),iTime*.07);
	p=rot(p,vec3(0,1,0),iTime*2.);
    p.zx=vec2(atan(p.z,p.x)/PI*.2, length(p.zx)-1.5);
    p.xy=vec2(atan(p.x,p.y)/PI*.5, length(p.xy)-1.);
    p.x+=p.z;
    p.x=mod(p.x,.2)-.1;
    vec2 g=vec2(5,1);
    return (length(p.xy*g)-.3);
    //vec2 g=vec2(1,.2);
    //return (length(p.xy*g)-.05)*5.;
}

vec3 calcNormal(vec3 p)
{
    vec3 e=.05*vec3(-1,1,1);
    return normalize(e*map(p+e)+e.yxy*map(p+e.yxy)+e.yyx*map(p+e.yyx)-e.xxx*map(p-e.xxx));
}

float march(vec3 ro, vec3 rd, float near, float far)
{
    float t=near,d;
    for(int i=0;i<100;i++)
    {
        t+=d=map(ro+rd*t);
        if (d<.001) return t;
        if (t>=far) return far;
    }
    return far;
}

vec3 doColor(vec3 p)
{
    return vec3(.7,.5,.3)+cos(p*2.)*.5+.5;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = (fragCoord.xy*2.-iResolution.xy)/iResolution.y;
    vec3 ro = vec3(0,0,-6);
    vec3 rd = normalize(vec3(uv,3));
    vec3 col= vec3(0);
	const float maxd=50.;
    float t=march(ro,rd,0.,maxd);
    if(t<maxd)
    {
        vec3 p=ro+rd*t;
        col=doColor(p); 
        vec3 n=calcNormal(p);      
		vec3 lightPos=ro+vec3(2,5,2)*.7;
    	vec3 li=lightPos-p;
		float len=length(li);
		li/=len;
		float dif=clamp(dot(n,li),0.1,1.);
        col*=max(dif,0.);
        float rimd=pow(clamp(1.-dot(reflect(-li,n),-rd),0.,1.),2.5);
		float frn=rimd+2.2*(1.-rimd);
    	col*=frn*.8;
        col*=max(.5+.5*n.y,.1);
        col*=exp2(-2.*pow(max(0.,1.-map(p+n*.8)/.8),2.));
        col+=.7*vec3(.8,.6,.2)*pow(clamp(dot(reflect(rd,n),li),0.,1.),10.);
    }
    col=pow(col,vec3(1./2.2));
    fragColor.xyz=col;
}
