
mat2 mkrot(in float t)
{
    float s = sin(t);
    float c = cos(t);
    return mat2(c,-s,s,c);
}

void rotCam(inout vec3 ro, inout vec3 rd)
{
    mat2 a = mkrot(.4);
    
    ro.yz *= a;
    rd.yz *= a;

    mat2 b = mkrot(iTime*.4);
    
    ro.xz *= b;
    rd.xz *= b;
 
    mat2 c = mkrot(sin(iTime*.4) * .5);
    
    ro.xy *= c;
    rd.xy *= c;
}

vec2 pom(in vec2 uv, in vec3 i)
{
    float y = 0.0;

    float d = 2./256.;
    for (int k = 0; k < 512; k++)
    {
        float h = textureLod(iChannel0, uv, 2.5).r;
        if (abs(h - y) > 1.)
            break;
    
        y += i.y * d;
        uv += i.xz * d * 1e-1;
    }

    return uv;
}

vec3 pomNor(in vec2 uv)
{
    const vec2 eps = vec2(1e-2,0);
    float t = textureLod(iChannel0, uv + eps.xy, 2.5).r;
    float b = textureLod(iChannel0, uv - eps.xy, 2.5).r;
    float l = textureLod(iChannel0, uv - eps.yx, 2.5).r;
    float r = textureLod(iChannel0, uv + eps.yx, 2.5).r;
    
    return normalize(vec3(r-l, 1e-1, b-t));
}

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

    vec3 s = normalize(vec3(1,1,0));

    vec3 ro = vec3(0,-.1,-1);
    vec3 rd = normalize(vec3(uv, 1));
    rotCam(ro, rd);
    vec3 col = vec3(0);
    
    float t = -ro.y/rd.y;
    vec3 p = ro + rd * t;
    
    vec3 ap = abs(p);
    if (t > 0. && max(max(ap.x,ap.y),ap.z) < .5)
    {
        vec2 st = pom(p.xz, rd);
        vec3 n = pomNor(st);
        col = texture(iChannel0, st).rgb * dot(n, s);
    }

    fragColor = vec4(col,1.0);
}