
#include "/lib/taa/res_params.glsl"
#include "/lib/uniforms.glsl"
#define waterfog
varying vec2 texcoord;
uniform vec3 atmosphereUp;
uniform vec3 cameraPosition;
uniform float far;

uniform sampler2D depthtex0;
uniform sampler2D depthtex1;
uniform sampler2D colortex1;

uniform sampler2D colortex0;
uniform sampler2D colortex3;
uniform sampler2D colortex4;
uniform sampler2D colortex7;
uniform sampler2D colortex8;
uniform sampler2D colortex11;
uniform float nightmixInv;

uniform float aspectRatio;
uniform float frameTimeCounter;
uniform int isEyeInWater;
uniform mat4 gbufferProjectionInverse;
uniform mat4 gbufferModelViewInverse;

#include "/lib/color_transforms.glsl"
vec3 toScreenSpace(vec3 position)
{
    position = position * 2.0 - 1.0;
    position.xy = vec2(gbufferProjectionInverse[0].x, gbufferProjectionInverse[1].y) * position.xy +
                  gbufferProjectionInverse[3].xy;
    return vec3(position.xy, gbufferProjectionInverse[3].z) /
           (gbufferProjectionInverse[2].w * position.z + gbufferProjectionInverse[3].w);
}
#ifdef VOLUMETRIC_LIGHTING

#include "/lib/fog/fog3.glsl"
#include "/lib/fog/fogdh.glsl"
#else

#include "/lib/fog/fog3_org.glsl"
#include "/lib/fog/fogdh_org.glsl"
#endif
uniform float near;
float ld(const float dist)
{
    return (2.0 * near) / (far + near - dist * (far - near));
}
/////

/////

#include "/lib/ssaodh.glsl"

vec3 getDepthPoint(vec2 coord, float depth)
{
    vec4 pos;
    pos.xy = coord;
    pos.z = depth;
    pos.w = 1.0;
    pos.xyz = pos.xyz * 2.0 - 1.0; // convert from the 0-1 range to the -1 to +1 range
    pos = gbufferProjectionInverse * pos;
    pos.xyz /= pos.w;

    return pos.xyz;
}

vec3 constructNormal(float depthA, vec2 texcoords, sampler2D depthtex)
{
    const vec2 offsetB = vec2(0.0, 0.001);
    const vec2 offsetC = vec2(0.001, 0.0);

    float depthB = texture(depthtex, texcoords + offsetB).r;
    float depthC = texture(depthtex, texcoords + offsetC).r;

    vec3 A = getDepthPoint(texcoords, depthA);
    vec3 B = getDepthPoint(texcoords + offsetB, depthB);
    vec3 C = getDepthPoint(texcoords + offsetC, depthC);

    vec3 AB = normalize(B - A);
    vec3 AC = normalize(C - A);

    vec3 normal = -cross(AB, AC);
    // normal.z = -normal.z;

    return normalize(normal);
}

void main()
{

    /* DRAWBUFFERS:05 */
    gl_FragData[1] = vec4(0.0);

    float z = texture(depthtex0, texcoord).x;
    float z0DH = 0.0;
    if (z > 0.0)
        z0DH = texture(dhDepthTex0, texcoord).x;

    vec3 color = texture(colortex0, texcoord.xy).rgb;
    if (z0DH >= 1.0 && z >= 1.0)
    {
        gl_FragData[0].rgb = texture(colortex8, texcoord).rgb;
        return;
    }
    vec3 fragpos = toScreenSpace(vec3(texcoord, z));
    vec3 fragposDH = toScreenSpaceDH(vec3(texcoord, z0DH));

    vec3 DH = texture(colortex5, texcoord).rgb;
    vec3 viewNormal = cross(dFdx(fragposDH), dFdy(fragposDH));

    DH *= vec3(clamp(ssao(fragposDH, noise_standard(gl_FragCoord.xy), viewNormal), 0, 1));

    float mixfactor = GetBorderFogMixFactor(fragpos, far, 0.0);

    color.rgb = mix(color.rgb, DH, mixfactor);

    gl_FragData[0].rgb = color;

    // gl_FragData[0].rgb = vec3(translucents.ab);
}
