// Code by Flopine
// using simesgreen shader : https://www.shadertoy.com/view/Msf3Dj
// Thanks to wsmind, leon, lsdlive, XT95, lamogui and Coyhot for teaching me :)
// Thanks LJ for giving me the love of shadercoding :3


#define ITER 64
#define PI 3.141592
#define minStep 0.02
#define hitThreshold 0.01

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

vec2 mo (vec2 p, vec2 d)
{
    p = abs(p)-d;
    if (p.y > p.x) p.xy = p.yx;
    return p;
}

vec2 moda(vec2 p, float per)
{
    float a = atan(p.y,p.x);
    float l = length(p);
    a = mod(a-per/2., per) - per/2.;
	return vec2 (cos(a),sin(a))*l;
}

float stmin(float a, float b, float k, float n)
{
    float st = k/n;
    float u = b-k;
    return min(min(a,b), 0.5 * (u+a+abs(mod(u-a+st, 2.*st)-st)));
}

float od (vec3 p, float d)
{
    return dot(p, normalize(sign(p)))-d;
}

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

float sphe (vec3 p, float r)
{return length(p)-r;}

float sc(vec3 p, float s) 
{
    p.xz *= rot(iTime);
    p = abs(p);
    p = max(p, p.yzx);
    return min(p.x, min(p.y, p.z)) - s;
}

float prim1 (vec3 p)
{
    p.xy = moda(p.xy, 2.*PI/7.);
   	p.x -= 2.5;
    return max(-sc(p, 0.6), od(p,1.));
}

float prim2 (vec3 p)
{ 
    p.xy *= rot(iTime*0.3);
    p.xy = mo(p.xy, vec2(3.));
    p.xy = moda(p.xy, 2.*PI/5.);
    p.x -= 3.8;
    return stmin(prim1(p),sphe(p,1.5),0.6,3.);
}

float SDF (vec3 p)
{
    float b = box(p, vec3(15.,10.,1.));
    float d = max(b, -prim2(p));
  	d += texture(iChannel0, p.xy).r*0.04;
    return d;
}

//simesgreen raymarched inside function : https://www.shadertoy.com/view/Msf3Dj
vec3 traceInside(vec3 ro, vec3 rd, out bool hit, out float insideDist)
{
    
    hit = false;
    insideDist = 0.0;	
    vec3 pos = ro;
    vec3 hitPos = pos;
    for(int i=0; i<ITER; i++)
    {
		float d = SDF(pos);
		d = max(abs(d), minStep) * sign(d);// enforce minimum step size
		
		if (d < hitThreshold && !hit) {
			// save first hit
			hitPos = pos;
			hit = true;
		}
		
		if (d < 0.01) {
			// sum up distance inside
			insideDist += d;
		}
		pos += abs(d)*rd*0.45;
    }
    return hitPos;
}

vec3 getcam (vec3 eye, vec3 lookat, vec2 uv, float fov)
{
    vec3 forward = normalize(lookat-eye);
    vec3 right = normalize(cross(vec3(0.,1.,0.),forward));
    vec3 up = normalize(cross(forward, right));
    return normalize(forward*fov+right*uv.x+up*uv.y);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = 2.*(fragCoord/iResolution.xy)-1.;
	uv.x *= iResolution.x/iResolution.y;
    
    vec3 ro = vec3(0.,-1.3, -5.); 
    vec3 p = ro;
    vec3 target = vec3(0.);
    vec3 rd = getcam(ro, target, uv, 0.8);
    
    vec3 translucentColor = vec3(0.1, 0.2, length(uv*0.5));
    // trace ray
    bool hit;
    float dist;
    vec3 hitPos = traceInside(ro, rd, hit, dist);

    vec3 rgb = vec3(0.0);
    if(hit) 
    {
		// exponential fall-off:
		rgb = exp(-dist*dist*translucentColor);
     } 
      else 
      {
        rgb = vec3(0.94,1.,1.);
     }


    // Output to screen
    fragColor = vec4(pow(rgb, vec3(0.45)),1.0);
}
