#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.

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


#include "/lib/head.glsl"

#ifdef lightmapSmoothingEnabled
/*DRAWBUFFERS:03*/
layout(location = 0) out vec4 sceneColor;
layout(location = 1) out vec4 lightmapData;
#else
/*DRAWBUFFERS:0*/
layout(location = 0) out vec4 sceneColor;
#endif

#define ATROUS_SIZE 16

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

in vec2 coord;

#ifndef airTransmittanceHQ
flat in vec3 sunColor;
#endif

uniform sampler2D colortex0;
uniform sampler2D colortex3;
uniform sampler2D colortex5;
uniform sampler2D colortex6;

uniform sampler2D depthtex0;

uniform sampler2D noisetex;

uniform int worldTime;

uniform float far, near;

uniform vec2 taaOffset;
uniform vec2 pixelSize, viewSize;

uniform vec3 upvec, upvecView;
uniform vec3 sunvec, sunvecView;
uniform vec3 moonvec, moonvecView;

uniform vec4 daytime;

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


/* ------ includes ------*/
#define FUTIL_LINDEPTH
#define FUTIL_ROT2
#include "/lib/fUtil.glsl"

#include "/lib/util/kernel.glsl"
#include "/lib/light/atrousLightmap.glsl"

#include "/lib/util/transforms.glsl"
#include "/lib/atmos/air/const.glsl"
#include "/lib/atmos/project.glsl"
#include "/lib/util/bicubic.glsl"

vec3 sunDisk(vec3 viewDir) {
    vec3 v      = -viewDir;
    vec3 sv     = normalize(sunvecView + v);
    float sun   = dot(sv, v);

    const float size    = 0.0055;
    float maxsize       = size + 0.0004;
        maxsize        += linStep(sunvec.y, -0.04, 0.04)*0.004;

    float s   = 1.0-linStep(sun, size, maxsize);

    float limb = 1.0 - cube(linStep(sun, 0.0, maxsize))*0.8;
        s    *= limb;

    #ifdef airTransmittanceHQ
        return s * sunIllum * 5e3;
    #else
        return s * sunColor * 5e3;
    #endif
}

vec3 moonTexture(vec3 viewDir, vec3 color) {
    vec3 v      = -viewDir;
    vec3 sv     = normalize(moonvecView + v);
    float moon  = dot(sv, v);

    float s     = 1.0-linStep(moon, 0.03, 0.08);

    return color * s * moonIllum * 6.0;
}

#include "/lib/frag/noise.glsl"

vec3 skyStars(vec3 worldDir) {
    vec3 plane  = worldDir/(worldDir.y+length(worldDir.xz)*0.66);
    float rot   = worldTime*rcp(2400.0);
    plane.x    += rot*0.6;
    plane.yz    = rotatePos(plane.yz, (25.0/180.0)*pi);
    vec2 uv1    = floor((plane.xz)*768)/768;
    vec2 uv2    = (plane.xz)*0.04;

    vec3 starcol = vec3(0.3, 0.78, 1.0);
        starcol  = mix(starcol, vec3(1.0, 0.7, 0.6), noise2D(uv2).x);
        starcol  = normalize(starcol)*(noise2D(uv2*1.5).x+1.0);

    float star  = 1.0;
        star   *= noise2D(uv1).x;
        star   *= noise2D(uv1+0.1).x;
        star   *= noise2D(uv1+0.26).x;

    star        = max(star-0.25, 0.0);
    star        = saturate(star*4.0);

    return star*starcol*0.25*sqrt(daytime.w);
}

void main() {
    sceneColor      = texture(colortex0, coord);
    sceneColor.rgb  = linearToAP1Albedo(sceneColor.rgb);

    float sceneDepth = texture(depthtex0, coord).x;

    if (!landMask(sceneDepth)) {
        vec3 viewPos    = screenToViewSpace(vec3(coord, sceneDepth));
        vec3 viewDir    = normalize(viewPos);
        vec3 scenePos   = viewToSceneSpace(viewPos);
        vec3 sceneDir   = normalize(scenePos);

        vec3 sunMoon    = sunDisk(viewDir) + moonTexture(viewDir, sceneColor.rgb) + skyStars(sceneDir);

        sceneColor.rgb  = textureBicubic(colortex5, projectSky(sceneDir)).rgb;

        #ifdef airTransmittanceHQ
            vec3 transmittance = textureBicubic(colortex5, projectSky(sceneDir) + vec2(0.0, exp2(-SKY_RENDER_LOD) + pixelSize.y)).rgb;
        #else
            float transmittance = cube(linStep(sceneDir.y, -0.02, 0.02));
        #endif

        #if (defined cloudVolumeEnabled || defined cloudCirrusEnabled)
            const float clod = sqrt(CLOUD_RENDER_LOD);
            vec2 cloudCoord = (coord)*rcp(clod)+vec2(1.0-rcp(clod), 0.0);

            vec4 clouds     = textureBicubic(colortex5, cloudCoord);

            sceneColor.rgb  = sceneColor.rgb * clouds.a + clouds.rgb;

            sceneColor.rgb += sunMoon * transmittance * mix(1.0, clouds.a, cubeSmooth(saturate((sceneDir.y - 0.05) * 14.0)));
        #else
            sceneColor.rgb += sunMoon * transmittance;
        #endif
    }

    sceneColor      = clamp16F(sceneColor);

    #ifdef lightmapSmoothingEnabled
    lightmapData    = clamp16F(lightmap3x3(colortex3, depthtex0, colortex6, coord, ATROUS_SIZE));
    #endif
}