export default `#define MAX_STEPS 1280
#define MAX_DIST 1280.
#define E 0.00001
#define PI 3.141592

vec3 rotX(vec3 v, float a) {
    return vec3(v.x, v.y * cos(a) - v.z * sin(a), v.y * sin(a) + v.z * cos(a));
}
vec3 rotY(vec3 v, float a) {
    return vec3(v.x * cos(a) + v.z * sin(a), v.y, v.z * cos(a) - v.x * sin(a));
}
vec3 rotZ(vec3 v, float a) {
    return vec3(v.x * cos(a) - v.y * sin(a), v.x * sin(a) + v.y * cos(a), v.z);
}

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

//##########################################
//   Space folding
//##########################################
void planeFold(inout vec4 z, vec3 n, float d) {
	z.xyz -= 2.0 * min(0.0, dot(z.xyz, n) - d) * n;
}
void sierpinskiFold(inout vec4 z) {
	z.xy -= min(z.x + z.y, 0.0);
	z.xz -= min(z.x + z.z, 0.0);
	z.yz -= min(z.y + z.z, 0.0);
}
void mengerFold(inout vec4 z) {
	float a = min(z.x - z.y, 0.0);
	z.x -= a;
	z.y += a;
	a = min(z.x - z.z, 0.0);
	z.x -= a;
	z.z += a;
	a = min(z.y - z.z, 0.0);
	z.y -= a;
	z.z += a;
}
void boxFold(inout vec4 z, vec3 r) {
	z.xyz = clamp(z.xyz, -r, r) * 2.0 - z.xyz;
}

//##########################################
//   Primitive DEs
//##########################################

float de_sphere(vec4 p, float r) {
	return (length(p.xyz) - r) / p.w;
}
float de_box(vec4 p, vec3 s) {
	vec3 a = abs(p.xyz) - s;
	return (min(max(max(a.x, a.y), a.z), 0.0) + length(max(a, 0.0))) / p.w;
}
float de_tetrahedron(vec4 p, float r) {
	float md = max(max(-p.x - p.y - p.z, p.x + p.y - p.z),
				max(-p.x + p.y + p.z, p.x - p.y + p.z));
	return (md - r) / (p.w * sqrt(3.0));
}
float de_capsule(vec4 p, float h, float r) {
	p.y -= clamp(p.y, -h, h);
	return (length(p.xyz) - r) / p.w;
}

vec3 test = vec3(0.);

//##########################################
//   Main DEs
//##########################################

float de_fractal(vec4 p) {
	for (int i = 0; i < 8; ++i) {
		p.xyz = abs(p.xyz);
		p.xyz = rotZ(p.xyz, iTime * 0.1);
		mengerFold(p);
		p.xyz = rotX(p.xyz, iTime * 0.637 * 0.1);
        sierpinskiFold(p);
		p.xyz = rotX(p.xyz, iTime * 0.337 * 0.1);
		p *= vec4(1.);
		p.xyz += vec3(0.);
	}
	return de_box(p, vec3(6.0));
}

vec3 modlimSDF( in vec3 p, in float c, in vec3 l)
{
    return p-c*vec3(clamp(floor(p.x/c + 0.5),-l.x,l.x), clamp(floor(p.y/c + 0.5),-l.y,l.y), clamp(floor(p.z/c + 0.5),-l.z,l.z));
}

float sdfCross( in vec3 p )
{
  float a = 1.4 + 0.3*(sin(iTime * 1.));
  float da = de_box(vec4(p.xyz, 1.),vec3(1000.,a*1.0,a*1.0));
  float db = de_box(vec4(p.yzx, 1.),vec3(a*1.0,1000.,a*1.0));
  float dc = de_box(vec4(p.zxy, 1.),vec3(a*1.0,a*1.0,1000.));
  return min(da,min(db,dc));
}

float sdfFractal( in vec3 p )
{
    float d = de_fractal(vec4(p, 1.));

    float s = 1.0;

    for( int m=0; m<3; m++ )
    {
        vec3 a = modlimSDF(p*s, 0.5, vec3(1.));
        vec3 a2 = mod(p*s, 2.) - 1.;
        s *= 3.0;
        vec3 r = 1.0 - 3.0*abs(a);
        vec3 r2 = 1.0 - 3.0*abs(a2);

        float c = de_box(vec4(r, 1.), vec3(.5))/s;
        d = max(d, -c);
        c = de_box(vec4(r, 1.), vec3(.10))/s;
        d = max(d, -c);
        c = -sdfCross(r2)/s;
        d = max(d, -c);
        c = de_box(vec4(r.xyz + vec3(sign(r.x) / 5., sign(r.y) / 5.,sign(r.z) / 5.), 1.), vec3(.5))/s;
        d = min(d, c);
        if (m == 2)
            test.x = length(d);
        if (m == 3)
            test.y = length(d);
        if (m == 4)
            test.z = length(d);
    }

    return d;
}


float scene(vec3 p)
{
    int		index = -1;
    float d = 10000.;
    float sd2 = sdfFractal(p);
    d = min(sd2 * 0.2, d);
    return d;
}

bool hit = false;

vec2 march(vec3 ro, vec3 rd)
{
    float dO = 0.;
    float mind = 10000.;
    float index;
    int steps = 0;
    for (int isteps = 0; isteps < MAX_STEPS; isteps++)
    {
		steps = isteps;
        vec3 p = ro + rd * dO;
        float dS = scene(p);
        if (dS < mind)
            mind = dS;
        dO += dS;
        if (dS < E || dO > MAX_DIST)
            break;
    }
    if (steps == MAX_STEPS || dO > MAX_DIST)
        hit = false;
    else
        hit = true;
    return vec2(dO, mind);
}

vec2 march_light(vec3 ro, vec3 rd)
{
    float dO = 0.;
    float mind = 10000.;
    float index;
    for (int steps = 0; steps < MAX_STEPS; steps++)
    {
        vec3 p = ro + rd * dO;
        float dS = scene(p);
        if (dS < mind)
            mind = dS;
        dO += dS;
        if (dS < E || dO > MAX_DIST)
            break;
    }
    return vec2(dO, mind);
}

vec3 normal(vec3 p)
{
    float d = scene(p);
    vec2 e = vec2(0.001, 0);
    
    vec3 n = d - vec3(
        		scene(p - e.xyy),
                scene(p - e.yxy),
                scene(p - e.yyx));
    return (normalize(n));
}

float light(vec3 p, vec3 n)
{
    vec3 lightPos = vec3(-30. * sin(iTime), 0., -30. * cos(iTime));
    vec3 l = normalize(lightPos - p);
    
    float dif = clamp(dot(l, n), 0., 1.);
    //vec2 d = march_light(p+n*E * 30., l);
    //if (d.x < length(lightPos - p))
    //    	dif *= 0.1;
    return (dif);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = ((fragCoord - .5 * iResolution.xy) / iResolution.y);
   
    vec3 ro = vec3(-30. * sin(iTime), 0., -30. * cos(iTime));
    vec3 rd = normalize(vec3(uv.x, uv.y, 1.));
    rd = rotY(rd, iTime);
	vec3 col = vec3(0);
    
    vec2 d = march(ro, rd);

    vec3 p = ro + rd * d.x;
    vec3 n = normal(p);
    p += n * E * 10.;
    float dif = light(p, n);
    if (hit)
		col += dif;
    fragColor = vec4(col, 1.0);
}`;
