/*
====================================================================================================

    Copyright (C) 2020 RRe36

    All Rights Reserved unless otherwise explicitly stated.


    By downloading this you have agreed to the license and terms of use.
    These can be found inside the included license-file
    or here: https://rre36.com/copyright-license

    Violating these terms may be penalized with actions according to the Digital Millennium
    Copyright Act (DMCA), the Information Society Directive and/or similar laws
    depending on your country.

====================================================================================================
*/

/*DRAWBUFFERS:0*/
layout(location = 0) out vec3 sceneImage;

#include "/lib/head.glsl"
#include "/lib/util/colorspace.glsl"

#define INFO 0  //[0]

#define tonemapOperator ACES_AP1_SRGB   //[ACES_AP1_SRGB ACES_AP1_SRGB_RRT hejlBurgessAP1]

/* ------ color grading related settings ------ */
//#define doColorgrading

#define vibranceInt 1.00       //[0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 1.85 1.90 1.95 2.00]
#define saturationInt 1.00     //[0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 1.85 1.90 1.95 2.00]
#define gammaCurve 1.00        //[0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 1.85 1.90 1.95 2.00]
#define brightnessInt 0.00     //[-0.50 -0.45 -0.40 -0.35 -0.30 -0.25 -0.20 -0.15 -0.10 -0.05 0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.5]
#define constrastInt 1.00      //[0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 1.85 1.90 1.95 2.00]

#define colorlumR 1.00         //[0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 1.85 1.90 1.95 2.00]
#define colorlumG 1.00         //[0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 1.85 1.90 1.95 2.00]
#define colorlumB 1.00         //[0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 1.85 1.90 1.95 2.00]

//#define vignetteEnabled
#define vignetteStart 0.15     //[0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00]
#define vignetteEnd 0.85       //[0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00]
#define vignetteIntensity 0.75 //[0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00]
#define vignetteExponent 1.50  //[0.50 0.75 1.0 1.25 1.50 1.75 2.00 2.25 2.50 2.75 3.00 3.25 3.50 3.75 4.00 4.25 4.50 4.75 5.00]

in vec2 coord;

uniform sampler2D colortex0;
uniform sampler2D colortex2;
uniform sampler2D colortex3;
uniform sampler2D colortex4;

uniform sampler2D noisetex;

uniform int frameCounter;
uniform int isEyeInWater;

uniform float frameTimeCounter;
uniform float nightVision;

uniform vec2 bloomResolution;
uniform vec2 pixelSize;
uniform vec2 viewSize;

vec3 purkinje(vec3 hdr) {
    const vec3 reseponse = vec3(0.3, 0.50, 0.2);

    vec3 desatColor     = vec3(0.4, 0.6, 1.0);
        desatColor      = mix(desatColor, vec3(0.5, 0.9, 1.0), nightVision);

    float desat = dot(hdr, reseponse) * (1.0 + nightVision);
        hdr     = mix(hdr, vec3(desat)*desatColor, pow(1.0-linStep(desat, 0.0, 0.009 * (1.0 + nightVision)), 1.75));

    vec2 noisecoord = coord*viewSize;
    float anim  = frameTimeCounter*8*256;

    vec3 noise  = vec3(0.0);
        noise.r = texture(noisetex, floor(noisecoord+anim*1.8)*rcp(256.0)).x;
        noise.g = texture(noisetex, floor(noisecoord+vec2(-anim, anim)*1.2)*rcp(256.0)).x;
        noise.b = texture(noisetex, floor(noisecoord+vec2(anim, -anim)*1.4)*rcp(256.0)).x;

        hdr    += noise * sqrt(1.0-sstep(desat, 0.00, 0.008)) * 0.001;

    return hdr;
}

/* ------ tonemapping operators ------ */

#include "/lib/frag/academy/aces.glsl"

vec3 hejlBurgessAP1(vec3 AP1) {

        //AP1    *= 0.75;

    vec3 ACES   = AP1 * AP1_AP0;

    ACES    = max(ACES - 0.004, 0.0);
    ACES    = (ACES * (6.2 * ACES + 0.5)) * rcp(ACES * (6.2 * ACES + 1.7) + 0.06);
    ACES    = pow(ACES, vec3(2.2));     // Revert baked in gamma correction of Hejl-Burgess since we'd want to do it in sRGB instead
    ACES    = ACES * AP0_sRGB;

    return LinearToSRGB(ACES);
}

/* ------ color grading utilities ------ */

vec3 rgbLuma(vec3 x) {
    return x * vec3(colorlumR, colorlumG, colorlumB);
}

vec3 applyGammaCurve(vec3 x) {
    return pow(x, vec3(gammaCurve));
}

vec3 vibranceSaturation(vec3 color) {
    float lum   = dot(color, lumacoeff_rec709);
    float mn    = min(min(color.r, color.g), color.b);
    float mx    = max(max(color.r, color.g), color.b);
    float sat   = (1.0 - saturate(mx-mn)) * saturate(1.0-mx) * lum * 5.0;
    vec3 light  = vec3((mn + mx) / 2.0);

    color   = mix(color, mix(light, color, vibranceInt), saturate(sat));

    color   = mix(color, light, saturate(1.0-light) * (1.0-vibranceInt) / 2.0 * abs(vibranceInt));

    color   = mix(vec3(lum), color, saturationInt);

    return color;
}

vec3 brightnessContrast(vec3 color) {
    return (color - 0.5) * constrastInt + 0.5 + brightnessInt;
}

vec3 vignette(vec3 color) {
    float fade      = length(coord*2.0-1.0);
        fade        = linStep(abs(fade) * 0.5, vignetteStart, vignetteEnd);
        fade        = 1.0 - pow(fade, vignetteExponent) * vignetteIntensity;

    return color * fade;
}

void main() {
    vec3 sceneHDR   = stex(colortex0).rgb;

    #ifdef bloomEnabled
        vec2 cres       = max(viewSize, bloomResolution);

        float bloomInt = 0.16 + min(stex(colortex4).a, 2.0)*0.04;

        #if DIM == -1
            bloomInt  *= 1.3;
        #elif DIM == 1
            bloomInt  *= 1.5;
        #endif

        if (isEyeInWater == 1) bloomInt = mix(bloomInt, 1.0, 0.4);

        vec3 bloom  = texture(colortex3, coord/cres*bloomResolution*0.5).rgb * 4.0;  //apply bloom

        sceneHDR    = mix(sceneHDR, bloom, bloomInt);

        float rint      = stex(colortex2).y;
        bool rain       = rint > 0.0;

        if (rain) sceneHDR = mix(sceneHDR, bloom * 1.4, rint * 0.5);
    #else
        float rint      = stex(colortex2).y;
        bool rain       = rint > 0.0;

        if (rain) sceneHDR = mix(sceneHDR, sceneHDR * 1.4, rint * 0.5);
    #endif

    #ifndef DIM
        sceneHDR    = purkinje(sceneHDR);
    #endif

    #ifdef manualExposureEnabled
        sceneHDR   *= rcp(manualExposureValue);
    #else
        sceneHDR   *= stex(colortex4).a * exposureBias;
    #endif

    #if DIM == -1
        sceneHDR  *= 0.5;
    #elif DIM == 1
        sceneHDR  *= 1.0;
    #endif

    #ifdef doColorgrading
        sceneHDR    = vibranceSaturation(sceneHDR);
        sceneHDR    = rgbLuma(sceneHDR);
    #endif

    #ifdef vignetteEnabled
        sceneHDR    = vignette(sceneHDR);
    #endif

    vec3 sceneLDR   = tonemapOperator(sceneHDR);
    
    #if DEBUG_VIEW==5
        sceneLDR    = sqrt(sceneHDR);
    #endif

    #ifdef doColorgrading
        sceneLDR    = brightnessContrast(sceneLDR);
        sceneLDR    = applyGammaCurve(saturate(sceneLDR));
    #endif

    sceneImage      = saturate(sceneLDR);
}