#extension GL_ARB_gpu_shader5 : enable
#include "/lib/projections.glsl"
#include "/lib/taa/res_params.glsl"
#include "/lib/shadow_param.glsl"
#include "/lib/uniforms.glsl"

flat varying vec3 ambientUp;
flat varying vec3 ambientDown;
flat varying vec3 ambientLeft;
flat varying vec3 ambientRight;
flat varying vec3 ambientB;
flat varying vec3 ambientF;
flat varying float ambientA;
varying vec2 texcoord;
uniform vec3 sunPosWorld;
uniform vec3 atmosphereUp;
uniform float nightblendShadows;

uniform float frameTimeCounter;

uniform float darknessLightFactor;
uniform sampler2D depthtex0;


uniform sampler2D colortex8; // data0
uniform sampler2D colortex5; // data0
uniform sampler2D colortex0; // albedo
#include "/lib/color_transforms.glsl"
#include "/lib/light.glsl"





#include "/lib/shadows/shadowfuncdh.glsl"
// #include "/lib/ssao.glsl"
float rayTraceShadow(vec3 dir, vec3 position, float dither, float sss)
{
    const float quality = 9;

    vec3 clipPosition = toClipSpace3DH(position);

    float rayLength =
        ((dir.z * dhFarPlane + position.z) > -dhNearPlane) ? dir.z / (-dhNearPlane - position.z) : dhFarPlane;

    vec3 direction = toClipSpace3DH(position + dir * rayLength) - clipPosition;

    direction.xyz = direction.xyz / max(abs(direction.x) / texelSize.x, abs(direction.y) / texelSize.y);

    vec3 stepv = (direction * 2);

    float tolerance = 0.005;

    for (int i = 0; i < quality; i++)
    {
        vec3 spos = clipPosition + stepv * (float(i) + (dither + 0.3));

        float sp = texelFetch2D(dhDepthTex0, ivec2(spos.xy / texelSize), 0).r;
        if (sp < spos.z && abs(tolerance - (spos.z - sp)) < tolerance)
        {
            return 0.0;
        }
    }

    return 1.0;
}

vec3 calcAmbientLightDH(vec2 lightmap, float RSML, float diffuseSun, vec3 torch)
{

    // Extract skymap value from lightmap
    float skymap = lightmap.y;
// Adjust skymap value if not in the overworld
#ifndef OVERWORLD
    skymap += 5;
#endif

    // Calculate combined ambient light contributions
    vec3 ambientCombined = ((ambientUp * 2)) * skymap + RSML;

    // Calculate the diffuse light contribution from the sun and ambient light
    vec3 diffuseLight = diffuseSun * sunLight + ambientCombined;

    // Calculate darkness factor based on darknessLightFactor
    float darknessFactor = darknessLightFactor * darknessLightFactor * darknessLightFactor;

    // Apply darkness factor to diffuse light
    diffuseLight *= (1.0 - 6.0 * darknessFactor);

    // Combine diffuse light with torch light and apply minimum clamping
    vec3 light = max(diffuseLight + torch + (vec3(0.002, 0.005, 0.006) * (1 + screenBrightness * 2.0)), 0.001);

    // Apply final darkness factor
    light *= 1 - darknessLightFactor;

    // Return the calculated light
    return light;
}

void main()
{
    /* DRAWBUFFERS:5*/
    vec3 color;
    float z = texture(dhDepthTex0, texcoord).x;

    if (z >= 1)
    {
        color = texture(colortex8, texcoord).rgb;
    }
    else
    {
        vec3 data1 = texelFetch(colortex5, ivec2(gl_FragCoord.xy), 0).rgb;

        vec3 albedo = unpack(data1.r).rgb;

        vec2 lightmap = clamp(unpack2(data1.g).rg - 0.03, 0, 1);
        float diffuseSun = clamp(unpack2(data1.g).b, 1, 1);
        vec3 fragpos = toScreenSpaceDH(vec3(texcoord, z));
        vec3 p3 = mat3(gbufferModelViewInverse) * fragpos + gbufferModelViewInverse[3].xyz;

        diffuseSun = shadowFunc(diffuseSun, 0, p3, noise_standard(gl_FragCoord.xy), lightmap.xy);

        // diffuseSun *= rayTraceShadow(sunVec, fragpos, noise_standard(gl_FragCoord.xy), 0);
        // diffuseSun *= clamp((pow(lightmap.y, 16) * 2 - 0.1), 0, 1);
        vec3 torch = vec3(3.000, 1.382, 0.408);

        float lightmapX_powed = lightmap.x * lightmap.x; // lightmap.x ^ 2
        lightmapX_powed *= lightmapX_powed * lightmap.x; // lightmap.x ^ 5

        torch *= (lightmapX_powed)*lightmap.x;

        vec3 ambient = calcAmbientLightDH(lightmap.xy, 0.6 * ambientA * lightmap.y, diffuseSun, torch);

        color = ambient * albedo;

        //color = vec3(diffuseSun) * vec3(1, 0.5, 0.5);
    }

    gl_FragData[0].rgb = color;
}
