#version 330 core

// inputz
in vec2 UV;
in vec2 ray;
uniform sampler2D colors;
uniform sampler2D normals;
uniform sampler2D dbuffer;
uniform mat4 M;
uniform float rad;
uniform float rcRadius;

// outputz
out vec4 color;

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

float rand(vec2 co){
    return (fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453) - 0.5) * 2.0;
}

vec3 coordinates() {
    float z = texture(dbuffer, UV).x; // * 2.0 - 1.0;
    vec4 projd = vec4(UV, z, 1.0);
    vec4 pos = inverse(M) * projd;
    pos /= pos.w;
    return pos.xyz;
}

#define Nsamples 32.0
float ssao() {
    float ao = 0.0;
    float origz = texture(dbuffer, UV).x;
    vec4 origin = inverse(M) * vec4(UV, origz, 1.0);

    for (int i = 0; i < int(Nsamples); i++) {
        vec2 candidate = UV + rad * rotate(6.283185 * rand(UV + 0.1 * vec2(i * UV.y, UV.x + origz))) * vec2(1.0, 0.0);
        float sampleDepth = texture(dbuffer, candidate).x;
        vec4 samplepos = inverse(M) * vec4(candidate, sampleDepth, 1.0);
        float range = abs(origz - sampleDepth);
        vec3 na = texture(normals, UV).xyz;
        float normalfactor = max(0.0, dot(normalize(samplepos.xyz - origin.xyz), na));
        ao += (sampleDepth <= origz ? 1.0 : 0.6) * normalfactor; // / max(1.0, 0.1*range * range)
    }
    return max(1.0, 1.0 - ao / Nsamples);
}

void main() {
    color = vec4(vec3(ssao()), 1.0);
}
