#define R (iResolution.xy)
#define T (iTime)
#define M_PI (3.14159265359)
#define TAU (M_PI * 2.0)
#define ZERO (min(0, int(iTime)))
#define adot(a,b) (abs(dot(a, b)))
#define cdot(a,b) (max(0.0, dot(a, b)))
#define rgb(a,b,c) (vec3(a, b, c) / 255.0)
mat2 rot(in float a) { float c = cos(a); float s = sin(a); return mat2(c, s, -s, c); }
vec3 noise(in vec3 p, in float seed) { return textureLod(iChannel3, (p+(seed*1.928271731))/10., 0.0).xyz;}

vec3 snoise(in vec3 p, in float seed) {
    vec3 id = floor(p);
    vec3 lv = fract(p);
    lv = lv*lv*(3.0-2.0*lv);
    
    return mix(
    mix(
        mix(noise(id + vec3(0, 0, 0), seed), noise(id + vec3(1, 0, 0), seed), lv.x),
        mix(noise(id + vec3(0, 1, 0), seed), noise(id + vec3(1, 1, 0), seed), lv.x),
        lv.y
    ),
    mix(
        mix(noise(id + vec3(0, 0, 1), seed), noise(id + vec3(1, 0, 1), seed), lv.x),
        mix(noise(id + vec3(0, 1, 1), seed), noise(id + vec3(1, 1, 1), seed), lv.x),
        lv.y
    ), lv.z);
}

vec3 snoise(in vec3 p, in float seed, in float freq) {
    float div = 0.0;
    float amp = 1.0;
    vec3 n = vec3(0.0);
    #define ADV n += amp*snoise(p*freq, seed); div += amp; amp /= 2.0; freq *= 2.0;
    ADV;ADV;ADV;ADV;ADV;ADV;
    #undef ADV
    return n / div;
}

float sdf(in vec3 p) {
    float time = T*0.1;
    vec3 shift = (0.5+(0.5*cos(time)))*vec3(cos(time)*0.5, sin((time*1.6)+1.2938871875)*2., sin(time-4.88827715)*0.5);
    vec3 n1 = snoise((p+shift)*0.1, 1.293915, 10.);
    shift += (0.5+(n1*4.))*vec3(sin((time+(n1.x*2.0-1.0))), cos((time+(n1.y*2.0-1.0))), cos((time+(n1.z*2.0-1.0))));
    vec3 n2 = snoise(((p-shift)*0.1)+(n1*0.5), 0.09928913, 10.) * 2.0 - 1.0;
    vec3 n = reflect(n1, n2);
    return clamp(length(n+(dot(n1, n2)/2.)) - length(p/2.), 0.0, 2.0);
}

vec3 march(in vec3 ro, in vec3 rd) {
    float d = 0.0;
    vec3 col = vec3(0.0);
    float sum = 0.0;
    for (float d = 10.0; d > 0.0;  d -= 0.5) {
        vec3 p = ro+(rd*d*1.3); float next = sdf(p); sum += next;
        if (sum > 0.001) col += snoise(p, 2.2232124, 3.5)*max(0.0, next - sdf(p + normalize(vec3(1, 2, -3))));   
    }
    
    return col;
}

vec3 sky(in vec3 rd) {
    vec3 c1 = rgb(1, 1, 1);
    vec3 c2 = rgb(66, 66, 66);  
    float dotup = max(0.0, dot(rd, vec3(0, 1, 0)));
    return mix(c1, c2, clamp(dotup*dotup, 0.0, 1.0));
}

void mainImage( out vec4 O, in vec2 fc )
{
    vec3 col = vec3(0.0);
    vec4 m = iMouse;
    vec2 uv = (fc-0.5*R.xy)/R.y;
    m.xy = (m.xy-0.5*R.xy)/R.y;
    vec3 ro = vec3(0, 0.0, -5.0);
    vec3 rd = normalize(vec3(uv.xy, 1.0));
    if (m.z > 0.001) {
        ro.yz *= rot(m.y*TAU); ro.xz *= rot(m.x*TAU);  
        rd.yz *= rot(m.y*TAU); rd.xz *= rot(m.x*TAU);
    }
    col = sky(rd);
    col += march(ro, rd);
    col /= vec3(1.0) + col;
    col = pow(col, vec3(1.0 / 2.2));
    O = vec4(col, 1.0);
}