#include "/lib/config.glsl"

// Do not remove comments. It works!
/*

noisetex - Water normals
colortex0 - Unused
colortex1 - Antialiasing auxiliar
colortex2 - Bluenoise 
colortex3 - TAA Averages history
gaux1 - Screen-Space-Reflection / Bloom auxiliar
gaux2 - Clouds texture
gaux3 - Exposure auxiliar
gaux4 - Fog auxiliar

const int noisetexFormat = RG8;
const int colortex0Format = R8;
*/
#ifdef DOF
/*
const int colortex1Format = RGBA16F;
*/
#else
/*
const int colortex1Format = R11F_G11F_B10F;
*/
#endif
/*
const int colortex2Format = R8;
*/
#ifdef DOF
/*
const int colortex3Format = RGBA16F;
*/
#else
/*
const int colortex3Format = R11F_G11F_B10F;
*/
#endif
/*
const int gaux1Format = R11F_G11F_B10F;
const int gaux2Format = R8;
const int gaux3Format = R16F;
const int gaux4Format = R11F_G11F_B10F;

const int shadowcolor0Format = RGBA8;
*/

// Buffers clear
const bool colortex0Clear = false;
const bool colortex1Clear = false;
const bool colortex2Clear = false;
const bool colortex3Clear = false;
const bool gaux1Clear = false;
const bool gaux2Clear = false;
const bool gaux3Clear = false;
const bool gaux4Clear = false;

/* Uniforms */

#ifdef DEBUG_MODE
    uniform sampler2D shadowtex1;
    uniform sampler2D shadowcolor0;
    uniform sampler2D colortex3;
#endif

uniform sampler2D gaux3;
uniform sampler2D colortex1;
uniform float viewWidth;
uniform mat4 gbufferProjection;
uniform vec3 sunPosition;
uniform float rainStrength;

#if AA_TYPE == 3
    uniform float pixelSizeX;
    uniform float pixelSizeY;
#endif

/* Ins / Outs */

varying vec2 texcoord;
varying float exposure;

/* Utility functions */

#if AA_TYPE == 3
    // #include "/lib/post.glsl"
    #include "/lib/luma.glsl"
    #include "/lib/fxaa.glsl"
#endif

#include "/lib/basic_utils.glsl"
#include "/lib/tone_maps.glsl"

#ifdef COLOR_BLINDNESS
    #include "/lib/color_blindness.glsl"
#endif

#if CHROMA_ABER == 1
    #include "/lib/aberration.glsl"
#endif


vec3 prismaSunLookEffect(vec3 color) {
    vec4 sunClip = gbufferProjection * vec4(sunPosition, 1.0);
    float w = max(abs(sunClip.w), 1e-5);
    vec2 sunUv = sunClip.xy / w * 0.5 + 0.5;

    float onScreen = step(0.0, sunUv.x) * step(0.0, sunUv.y) * step(sunUv.x, 1.0) * step(sunUv.y, 1.0);
    float inFront = float(sunClip.z > 0.0);

    vec2 toSun = sunUv - texcoord;
    float dist = length(toSun);

    vec2 screenCenter = vec2(0.5);
    float centered = 1.0 - clamp(length(sunUv - screenCenter) * 3.6, 0.0, 1.0);
    centered = smoothstep(0.78, 0.992, centered);
    centered *= centered;
    centered *= centered;

    // Only keep the look-at-sun effect when the sun is close to the center.
    // This prevents the off-angle dusty particles around the sun.
    float localGlow = smoothstep(0.070, 0.0, dist);
    localGlow *= localGlow;
    localGlow *= centered;

    // A soft center-screen bloom that fades out quickly when you look away.
    float centerBloom = smoothstep(0.18, 0.0, length(texcoord - screenCenter));
    centerBloom *= centerBloom;

    // Small ghost toward screen center, but only while actually looking at the sun.
    vec2 ghostPos = mix(screenCenter, sunUv, -0.22);
    float ghost = smoothstep(0.055, 0.0, length(texcoord - ghostPos));
    ghost *= ghost;
    ghost *= centered;

    float strength = (1.0 - rainStrength) * onScreen * inFront * centered;
    vec3 flareTint = vec3(1.0, 0.86, 0.62);

    color += flareTint * (localGlow * 0.082 + centerBloom * 0.055 + ghost * 0.010) * strength;
    return color;
}


// MAIN FUNCTION ------------------

void main() {
    #if CHROMA_ABER == 1
        vec3 blockColor = color_aberration();
    #else
        vec3 blockColor = texture2D(colortex1, texcoord).rgb;
        #if AA_TYPE == 3 && !defined DOF
            blockColor = fxaa311(blockColor, 5);
        #endif
    #endif
    
    // Exposure correction
    blockColor *= vec3(exposure * 1.050);
    blockColor = custom_sigmoid(blockColor);

    // Gentle Prisma grade: slightly warmer, brighter and less dull without going candy-like.
    float prismaGradeLuma = dot(blockColor, vec3(0.2126, 0.7152, 0.0722));
    blockColor = mix(vec3(prismaGradeLuma), blockColor, 1.11);
    blockColor *= vec3(1.032, 1.018, 0.992);

    // Mild contrast lift so the world feels less flat, while keeping the cinematic softness.
    blockColor = (blockColor - vec3(0.5)) * 1.060 + vec3(0.5);
    blockColor = clamp(blockColor, vec3(0.0), vec3(16.0));

    // Color-grading -----
    // DEVELOPER: If your post processing effect only involves the current pixel,
    // it can be placed here. For example:

    // Saturation:
    // float actual_luma = luma(blockColor);
    // blockColor = mix(vec3(actual_luma), blockColor, 1.5);

    // Color-blindness correction
    #ifdef COLOR_BLINDNESS
        blockColor = color_blindness(blockColor);
    #endif

#ifndef THE_END
    blockColor = prismaSunLookEffect(blockColor);
#endif

    #ifdef DEBUG_MODE
        if(texcoord.x < 0.5 && texcoord.y < 0.5) {
            blockColor = texture2D(shadowtex1, texcoord * 2.0).rrr;
        } else if(texcoord.x >= 0.5 && texcoord.y >= 0.5) {
            blockColor = vec3(texture2D(gaux3, vec2(0.5)).r * 0.25);
        } else if(texcoord.x < 0.5 && texcoord.y >= 0.5) {
            blockColor = texture2D(colortex1, ((texcoord - vec2(0.0, 0.5)) * 2.0)).rgb;
        } else if(texcoord.x >= 0.5 && texcoord.y < 0.5) {
            blockColor = texture2D(shadowcolor0, ((texcoord - vec2(0.5, 0.0)) * 2.0)).rgb;
        } else {
            blockColor = vec3(0.5);
        }

        gl_FragData[0] = vec4(blockColor, 1.0);

    #else
        gl_FragData[0] = vec4(blockColor, 1.0);
    #endif
}