/* Creative Commons Licence Attribution-NonCommercial-ShareAlike 
   phreax 2021
*/

#define PI 3.141592
#define SIN(x) (sin(x)*.5+.5)
#define PALETTE 0


float tt, g_mat;
float g_gl = 0.;

// from "Palettes" by iq. https://shadertoy.com/view/ll2GD3
vec3 pal( in float t, in vec3 a, in vec3 b, in vec3 c, in vec3 d )
{
    return a + b*cos( 6.28318*(c*t+d) );
}

vec3 getPal(int id, float t) {

    id = id % 7;

    vec3          col = pal( t, vec3(.5,0.5,0.5),vec3(0.5,0.5,0.5),vec3(1.0,1.0,1.0),vec3(0.0,-0.33,0.33) );
    if( id == 1 ) col = pal( t, vec3(0.5,0.5,0.5),vec3(0.5,0.5,0.5),vec3(1.0,1.0,1.0),vec3(0.0,0.10,0.20) );
    if( id == 2 ) col = pal( t, vec3(0.5,0.5,0.5),vec3(0.5,0.5,0.5),vec3(1.0,1.0,1.0),vec3(0.3,0.20,0.20) );
    if( id == 3 ) col = pal( t, vec3(0.5,0.5,0.5),vec3(0.5,0.5,0.5),vec3(1.0,1.0,0.5),vec3(0.8,0.90,0.30) );
    if( id == 4 ) col = pal( t, vec3(0.5,0.5,0.5),vec3(0.5,0.5,0.5),vec3(1.0,0.7,0.4),vec3(0.0,0.15,0.20) );
    if( id == 5 ) col = pal( t, vec3(0.5,0.5,0.5),vec3(0.5,0.5,0.5),vec3(2.0,1.0,0.0),vec3(0.5,0.20,0.25) );
    if( id == 6 ) col = pal( t, vec3(0.8,0.5,0.4),vec3(0.2,0.4,0.2),vec3(2.0,1.0,1.0),vec3(0.0,0.25,0.25) );
    
    return vec3(col);
}

mat2 rot2(float a) { return mat2(cos(a), sin(a), -sin(a), cos(a)); }


// by Nusan
float curve(float t, float d) {
  t/=d;
  return mix(floor(t), floor(t)+1., pow(smoothstep(0.,1.,fract(t)), 10.));
}

float box(vec3 p, vec3 r) {
    vec3 d = abs(p) - r;
    return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
}

float rect( vec2 p, vec2 b, float r ) {
    vec2 d = abs(p) - (b - r);
    return length(max(d, 0.)) + min(max(d.x, d.y), 0.) - r;
}

vec3 transform(vec3 p) {

    float a = PI*.5 + iTime;
    p.xz *= rot2(a);
    p.xy *= rot2(a);
    
    return p;
}


vec3 repeat(inout vec3 p, vec3 size) {
	vec3 c = floor((p + size*0.5)/size);
	p = mod(p + size*0.5, size) - size*0.5;
	return c;
}

float map(vec3 p) {

    vec3 bp = p;
    p.yz *= rot2(PI*.25);
    
    p.z = abs(p.z) - 2.5;

    p.z = abs(p.z) + 2.5;
   // p.xy *= rot2(PI*.9+ .2*tt);
  //  p.xz *= rot2(PI*.9);
  //  p.z -= 1.;
    
    // map to log-spherical
    float r = length(p);
    p = vec3(log(r),
             acos(p.z / r),
             atan(p.y, p.x));
   

    float shrink = 1./abs(p.y-PI) + 1./abs(p.y) - 1./PI;
    
    float density = 20.;
    float scale = floor(density)/PI;
    p *= scale;
    
    p.x -= tt;

    p.y -= 0.7;
    
    vec3 q = p;
    //p = fract(p*.5) * 2. - 1.;
    
    vec3 id = repeat(p, vec3(1.9, 1, 1.));


    p.yz *= rot2(.25*PI);
    p.x *= shrink;
     
   // p.x = abs(p.x) - .5;
  
    g_mat = bp.y*.6+id.x;
    
    float w = 0.015;
    float d = length(p.xz) - w;
    d = min(d, length(p.xy) - w);
    
    d *= r/(scale*shrink);

    return d*.7;
}

// from iq
float softshadow( in vec3 ro, in vec3 rd, float mint, float maxt, float k )
{
    float res = 1.0;
    float ph = 1e20;
    for( float t=mint; t<maxt; )
    {
        float h = map(ro + rd*t);
        if( h<0.001 )
            return 0.0;
        float y = h*h/(2.0*ph);
        float d = sqrt(h*h-y*y);
        res = min( res, k*d/max(0.0,t-y) );
        ph = h;
        t += h;
    }
    return res;
}


void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = (fragCoord-.5*iResolution.xy)/iResolution.y;

    
    vec3 ro = vec3(0, .5, -4.),
         rd = normalize(vec3(uv, .7)),
         lp = vec3(0.,2., -15);
         
    vec3 p = ro;
    vec3 col;
    
    float t, d = 0.1;
    
    tt = iTime;
    
    float mat = 0.,
          gl  = 0.;
    
    for(float i=.0; i<100.; i++) {
    
        d = map(p);
        mat = g_mat;
        gl = g_gl;
        
        if(d < 0.0001 || t > 5.) break;
        
        t += d;
        p += rd*d;
    }
    vec2 e = vec2(0.0035, -0.0035);
     
    vec3 al = vec3(1.000,0.357,0.078);
    vec3 bg = vec3(0.651,0.827,0.910);
    if(d < 0.001) {
         vec3 n = normalize( e.xyy*map(p+e.xyy) + e.yyx*map(p+e.yyx) +
                            e.yxy*map(p+e.yxy) + e.xxx*map(p+e.xxx));
        
       
        vec3 l = normalize(lp-p);
        float dif = max(dot(n, l), .0);
        float spe = pow(max(dot(reflect(-rd, n), -l), .0),40.);
        
        float sss = smoothstep(0., 1., map(p + l * .4)) / .4;
        //float shd = softshadow(p, l, 0.01, 2., 15.0);

        al = getPal(PALETTE, mat*.2);
        col +=  .7*al*dif + .1*spe +  + .3*al*sss + .8*al;
        col *= 1.4;

     
    } else {
        col += bg*mix(.5, 1., (1.2-pow(dot(uv, uv), .8)));
    }
    
    col *= mix(.3, .8, (1.3-pow(dot(uv, uv), .8))); // vignette
    col = pow(col, vec3(.45)); // gamma
    
    // Output to screen
    fragColor = vec4(col, 1.0 - t * 0.3);
}
