#version 400 compatibility

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

    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:0123*/
layout(location = 0) out vec4 scene;
layout(location = 1) out uvec4 sceneData;
layout(location = 2) out vec4 data2;
layout(location = 3) out vec4 data3;

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

in vec2 coord;

flat in mat2x3 lightColor;

uniform sampler2D colortex0;
uniform usampler2D colortex1;
uniform sampler2D colortex2;
uniform sampler2D colortex3;
uniform sampler2D colortex5;
uniform sampler2D colortex6;

uniform sampler2D depthtex0;
uniform sampler2D depthtex2;

uniform float aspectRatio;
uniform float far, near;
uniform float sunAngle;

uniform vec2 taaOffset;
uniform vec2 viewSize;

uniform vec3 lightvec, lightvecView;

uniform mat4 gbufferModelView, gbufferModelViewInverse;
uniform mat4 gbufferProjection, gbufferProjectionInverse;

/* ------ includes ------ */
#include "/lib/util/transforms.glsl"

#define FUTIL_LINDEPTH
#define FUTIL_MAT16
#define FUTIL_LIGHTMAP
#include "/lib/fUtil.glsl"

#define ATROUS_POSTRT
#include "/lib/util/kernel.glsl"
#include "/lib/light/indirect/atrousUpscale.glsl"

#define noBRDF
#include "/lib/frag/labPBR.glsl"


/* ------ metal albedo encoding ------ */

float bayer2e(vec2 a){
    a = floor(a);
    return fract( dot(a, vec2(.5, a.y * .75)) );
}
#define bayer4e(a)   (bayer2e( .5*(a))*.25+bayer2e(a))

#define m vec3(31,63,31)
float encode3x8(vec3 a){
    float dither = bayer4e(gl_FragCoord.xy);
    a += (dither-.5) / m;
    a = saturate(a);
    ivec3 b = ivec3(a*m);
    return float( b.r|(b.g<<5)|(b.b<<11) ) / 65535.;
}
#undef m


void main() {
    vec4 sceneColor   = stex(colortex0);
    float sceneDepth = stex(depthtex0).x;

    uvec4 tex1          = stex(colortex1);
        tex1.w          = pack2x16(vec2(encode3x8(sqrt(saturate(sceneColor.rgb))), 0.0));

    vec3 albedo         = sceneColor.rgb;

    #if DEBUG_VIEW!=4
    if (landMask(sceneDepth)) {
            vec2 d1     = unpack2x16(tex1.y);
        vec2 sceneLmap  = decode2x8(d1.x);

        int matID       = decodeMatID16(d1.y);

        vec4 specularData = unpack4x8(tex1.z);

        materialLAB matLAB = decodeSpecularTexture(specularData);

        #if DEBUG_VIEW==1
        sceneColor.rgb    = vec3(1.0);
        #endif

        /* ------ lighting ------ */

        vec3 indirectLight = atrous3x3(colortex3, depthtex0, colortex6, coord, 1).rgb;

        vec3 result     = indirectLight;

        float emission  = stex(colortex2).z;

        #ifdef emitterBoostEnabled
        if (emission > 0.001) {
            bool hand       = stex(depthtex0).x < stex(depthtex2).x;
            float albedoLum     = getLuma(sceneColor.rgb);
            vec3 emitterCol     = mix(lightColor[1], vec3(v3avg(lightColor[1])), emitterRecoloring);
                //emitterCol     *= cubeSmooth(saturate(v3avg(sceneColor.rgb) * 1.5));
                emitterCol    *= saturate(mix(cube(albedoLum) * normalize(sceneColor.rgb), sceneColor.rgb, albedoLum));
            result += emitterCol * 2.0 * emission * (1.0 - float(hand));
        }
        #endif

        sceneColor.rgb *= result;

        #if DEBUG_VIEW==2
        sceneColor.rgb    = ao * lightColor[0] * 2.0;
        #endif

        #if DEBUG_VIEW==3
            sceneColor.rgb    = indirectLight;

            #ifdef DEBUG_WITH_ALBEDO
                sceneColor.rgb *= albedo;
            #endif
        #endif
    } 
    #endif

    if (!landMask(sceneDepth)) {
        sceneColor.rgb  = vec3(1.0, 0.2, 0.05) * 0.02;
    }

    scene       = makeDrawbuffer(sceneColor);
    sceneData   = tex1;
    data2       = vec4(0.0);
    data3       = vec4(0.0);
}