#include "/lib/all_the_libs.glsl"

varying vec2 texcoord;

#include "/global/post/taa.glsl"

#if TAA_MODE != 0 || REFLECTIONS >= 2
/* DRAWBUFFERS:04 */
#else
/* DRAWBUFFERS:0 */
#endif

// Color grading, Bloom final, TAA final

vec3 motion_blur(vec3 Color, vec2 PrevCoord, vec2 CurrentCoord) {
    vec2 Velocity = PrevCoord - CurrentCoord;
    vec2 Offset = Velocity / 4 * MOTION_BLUR_STRENGTH;
    Offset *= 0.01666 / frameTime; // Adjust based on framerate. 60 fps is the baseline
    vec3 Blur = Color;

    float Noise = bayer8(gl_FragCoord.xy);
    CurrentCoord += Offset * Noise;

    for (int i = 1; i < 4; i++) {
        Blur += texture2D(colortex0, CurrentCoord).rgb;
        CurrentCoord += Offset;
    }
    return Blur / 4;
}

float getLuminance(vec3 color) {
    return dot(color, vec3(0.7125, 0.7154, 0.0721));
}

void main() {
    vec4 Color = texture2D(colortex0, texcoord);

    #if TAA_MODE != 0 || defined MOTION_BLUR
    bool IsDH;
    float Depth = get_depth_solid(texcoord, IsDH);
    vec2 PrevCoord = toPrevScreenPos(texcoord, Depth, IsDH);
    #endif

    #ifdef MOTION_BLUR
    if (Depth >= 0.56) {
        Color.rgb = motion_blur(Color.rgb, PrevCoord, texcoord);
    }
    #endif

    #if TAA_MODE != 0
    gl_FragData[1].xyz = TAA(Color.rgb, vec3(texcoord, Depth), PrevCoord, IsDH);
    #elif REFLECTIONS >= 2
    gl_FragData[1] = Color;
    #endif

    #ifdef AUTO_EXPOSURE

    // 1. Sample average brightness using a grid pattern
    // A single pixel causes flickering, so we average 25 points around the center.
    float sceneLum = 0.0;
    float samples = 0.0;
    

    // 0.04 covers roughly the center 10-20% of the screen. 
    float spread = 0.04; 

    for (int i = -2; i <= 2; i++) {
        for (int j = -2; j <= 2; j++) {
            vec2 offset = vec2(float(i), float(j)) * spread;
            vec2 samplePos = clamp(vec2(0.5) + offset, 0.0, 1.0);
            
            vec3 sampleColor = texture2D(colortex0, samplePos).rgb;
            sceneLum += getLuminance(sampleColor);
            samples += 1.0;
        }
    }
    
    sceneLum /= samples; // Average the result

    // 2. define how bright you want the image to be
    float targetLum = EXPOSURE;

    // 3. Calculate exposure factor
    float exposure = targetLum / (sceneLum + 0.001);

    // 4. Clamp the exposure
    exposure = clamp(exposure, 0.1, 4.0);

    // 5. Apply weather darkening
    exposure *= clamp(1.0 - (rainStrength * 0.5 + thunderStrength * 0.5 + nightStrength), 0.6, 1.0);

    // 6. Apply to Color
    Color.rgb *= exposure;
    #else

    Color.rgb *= clamp(EXPOSURE-(rainStrength+thunderStrength),0.5,3);

    #endif

    Color.rgb = apply_tonemap(Color.rgb);

    #if TONEMAP_OPERATOR != 3
    Color.rgb = pow(Color.rgb, vec3(1 / 2.2)); // Gamma correction
    #endif

    #if DEBUG_SHOW_BUFFER == 0
    gl_FragData[0] = Color;
    #elif DEBUG_SHOW_BUFFER == 1
    gl_FragData[0] = texelFetch2D(colortex1, ivec2(gl_FragCoord.xy), 0);
    #elif DEBUG_SHOW_BUFFER == 2
    gl_FragData[0] = texelFetch2D(noisetex, ivec2(gl_FragCoord.xy), 0);
    #elif DEBUG_SHOW_BUFFER == 3
    gl_FragData[0] = texelFetch2D(depthtex0, ivec2(gl_FragCoord.xy), 0);
    #else
    gl_FragData[0] = texelFetch(gaux1, ivec2(gl_FragCoord.xy), 0);
    #endif
}