uniform vec3 skycolnight;
uniform vec3 skyColorNight;
uniform vec3 sunPosWorld;
uniform float lightRadiance;
uniform float nightblend5;

uniform float nightblend5Inv;

uniform float sunpow;
const vec3 SR = vec3(0.000002901, 0.000006779, 0.00001655);
const vec3 SM = vec3(0.000007992, 0.000007992, 0.00000799);
const vec3 SL = vec3(10.44800000, 19.43500000, 37.1880000);

vec3 fogAtmosphere2(vec3 rayDir, float rayL, float rayL2, inout vec3 transmittance)
{
#ifdef END
    float lightRadiance = 0.01;
    vec3 lightPos = vec3(0.0);

#endif
#ifdef NETHER
    float lightRadiance = 0.5;
    vec3 lightPos = vec3(0.0);

#endif

    rayDir = normalize(rayDir);
    float t2 = -(6371000.0 * rayDir.y) + sqrt(40589641000000.0 * rayDir.y * rayDir.y + 1284200000000.0);
    float CT = dot(rayDir, lightPos);
    float PR = 0.12 * (1.0 + CT * CT);
    float term = 1.7225 - 1.7 * CT;

    vec2 OD = min(vec2(rayL, rayL2), t2);
    float h = (1.0 - 1.0 / (2.0 + t2 * t2 * 0.0000000000009));
    float DR = h * h;
    float DM = h * h * h * h * h * rainStrengthInv;
    float PM = (0.2775 / (12.5664 * sqrt(term) * term)) * 0.5;
    float t = clamp((lightPos.y - 1.0) / (-1.4), 0.0, 1.0);
    float LPS = pow(t * t * (3.0 - 2.0 * t), 8.0) * h;

    vec3 LC = lightRadiance * exp(-SL * LPS);
    vec3 R = (1.0 - exp(-OD.x * DR * SR)) * PR * LC;
    vec3 M = (1.0 - exp(-OD.x * DM * SM)) * PM * LC;
    vec3 S = (R + M) * sunpow;

#ifdef OVERWORLD

    vec3 TS = S * 16.0 + 0.01;
    float DP = dot(TS, vec3(0.299, 0.587, 0.114));
    float DP2 = dot(S, vec3(0.299, 0.587, 0.114));

    vec3 RC = mix(vec3(0.4, 0.5, 0.6), vec3(0.016, 0.05, 0.066), (1 - nightblend5));
    vec3 NC = vec3(0.04, 0.1, 0.11);

    S = mix(S, DP * NC, (1 - nightblend5));
    S = mix(S, DP2 * RC, rainStrength * (nightblend5));

    transmittance = exp(-OD.y * DR * vec3(0.000007836, 0.00001457625, 0.000027891));
    transmittance = mix(transmittance, transmittance * RC, rainStrength * 0.5);

#else

#ifdef END
    S = S * 10;
    S = (dot(S, vec3(0.299, 0.587, 0.114)) * vec3(0.184, 0.169, 0.212) * 2.0) + S * 0.1;

    transmittance = exp(-OD.y * DR * (1 - vec3(0.184, 0.169, 0.212)) / 20000);
    transmittance += exp(-OD.y * DR * vec3(0.000007836, 0.00001457625, 0.000027891)) * 0.2;

#else

    S = (dot(S * 4.0, vec3(0.299, 0.587, 0.114)) * fogColor) + S * 0.5;
    transmittance = exp(-OD.y * DR * (1 - vec3(0.184, 0.169, 0.212)) / 8000);
#endif
#endif

    return S;
}

vec3 fogAtmosphereALT(vec3 rayDir, float rayL, float rayL2, inout vec3 transmittance, float fogFactor)
{
#ifdef END
    float lightRadiance = 0.01;
    vec3 lightPos = vec3(0.0);

#endif
    rayDir = normalize(rayDir);
    float t2 = -(6371000.0 * rayDir.y) + sqrt(40589641000000.0 * rayDir.y * rayDir.y + 1284200000000.0);
    float CT = dot(rayDir, lightPos);
    float PR = 0.12 * (1.0 + CT * CT);
    float term = 1.7225 - 1.7 * CT;

    vec2 OD = min(vec2(rayL, rayL2), t2);
    float h = (1.0 - 1.0 / (2.0 + t2 * t2 * 0.0000000000009));
    float DR = h * h;
    float DM = h * h * h * h * h * rainStrengthInv;
    float PM = (0.2775 / (12.5664 * sqrt(term) * term)) * 0.5;
    float t = clamp((lightPos.y - 1.0) / (-1.4), 0.0, 1.0);
    float LPS = pow(t * t * (3.0 - 2.0 * t), 8.0) * h;

    vec3 LC = lightRadiance * exp(-SL * LPS);
    vec3 R = (1.0 - exp(-OD.x * DR * SR)) * PR * LC;
    vec3 M = (1.0 - exp(-OD.x * DM * SM)) * PM * LC;
    vec3 S = (R + M) * sunpow;

#ifdef OVERWORLD

    vec3 TS = S * 16.0 + 0.01;
    float DP = dot(TS, vec3(0.299, 0.587, 0.114));
    float DP2 = dot(S, vec3(0.299, 0.587, 0.114));

    vec3 RC = mix(vec3(0.4, 0.5, 0.6), vec3(0.016, 0.05, 0.066), (1 - nightblend5));
    vec3 NC = vec3(0.04, 0.1, 0.11);

    transmittance = exp(-OD.y * DR * vec3(0.000007836, 0.00001457625, 0.000027891));

    if (fogFactor > 0.0)
    {
        // 2nd sample (all the way to atmosphere exit), used for fog fade.
        vec3 R2 = (1.0 - exp(-t2 * DR * SR)) * PR * LC;
        vec3 M2 = (1.0 - exp(-t2 * DM * SM)) * PM * LC;
        vec3 S2 = (mix(R, R2, 0.5) + M2) * sunpow;
        vec3 transmittance2 = exp(-t2 * DR * vec3(0.000007836, 0.00001457625, 0.000027891));

        // S2 *= mix(vec3(1, 0, 0), vec3(1, 1, 1), (fogFactor * fogFactor)); // Fog color test
        S = mix(S, S2, fogFactor);

        transmittance.xyz = mix(transmittance.xyz, transmittance2, fogFactor);
    }

    S = mix(S, DP * NC, (1 - nightblend5));
    S = mix(S, DP2 * RC, rainStrength * (nightblend5));

    transmittance = mix(transmittance, transmittance * RC, rainStrength * 0.5);

#else

#ifdef END
    S = S * 10;
    S = (dot(S, vec3(0.299, 0.587, 0.114)) * vec3(0.184, 0.169, 0.212) * 2.0) + S * 0.1;

    transmittance = exp(-OD.y * DR * (1 - vec3(0.184, 0.169, 0.212)) / 20000);
    transmittance += exp(-OD.y * DR * vec3(0.000007836, 0.00001457625, 0.000027891)) * 0.2;

#else

    S = dot(S + 0.01, vec3(0.299, 0.587, 0.114)) * fogColor * 2.0;
    transmittance = exp(-OD.y * DR * (1 - fogColor) / 20000);
#endif
#endif

    return S;
}

vec3 fogAtmosphere3(vec3 rayDir)
{
    rayDir = normalize(rayDir);
    vec3 lightPos = lightPos;

    float rainStrength = rainStrength;
    float rainStrengthInv = rainStrengthInv;
    float lightRadiance = lightRadiance;
    float sunpow = sunpow;
    float nightblend5Inv = nightblend5Inv;
    float t = clamp((lightPos.y - 1.0) / (-1.4), 0.0, 1.0);
    float LPS = pow(t * t * (3.0 - 2.0 * t), 8.0);

    ///
    float t2 = -(6371000.0 * rayDir.y) + sqrt(40589641000000.0 * rayDir.y * rayDir.y + 1284200000000.0);
    float H = 1.0 - 1.0 / (2.0 + t2 * t2 * 0.0000000000009);
    //
    float CT = dot(rayDir, lightPos);
    float PR = 0.12 * (1.0 + CT * CT);
    float term = 1.7225 - 1.7 * CT;

    ////
    float DM = pow(H, 5.0) * rainStrengthInv;
    float PM = 0.13875 / (12.5664 * sqrt(term) * term);

    vec3 LC = lightRadiance * exp(-SL * LPS * H);
    vec3 S = ((1.0 - exp(-t2 * H * H * SR)) * PR + (1.0 - exp(-t2 * DM * SM)) * PM) * LC;

    ///
    S = S * sunpow;

#ifdef OVERWORLD
    vec3 TS = S * 16.0 + 0.01;
    float DP = (TS.x) * 0.299 + (TS.y) * 0.587 + (TS.z) * 0.114;
    float DP2 = (S.x) * 0.299 + (S.y) * 0.587 + (S.z) * 0.114;

    vec3 RC = mix(vec3(0.4, 0.5, 0.6), vec3(0.016, 0.05, 0.066), nightblend5Inv);
    vec3 NC = vec3(0.04, 0.1, 0.11);

    S = mix(S, DP * NC, nightblend5Inv);
    S = mix(S, DP2 * RC, rainStrength);
#else
    S = dot(S + 0.01, vec3(0.299, 0.587, 0.114)) * fogColor * 2.0;
#endif

    return S;
}

vec3 sunColorFunc()
{
    float L = lightPos.y;
    float T = -(6371000.0 * L) + sqrt(40589641000000.0 * L * L + 1284200000000.0);
    float H = 1.0 - 1.0 / (2.0 + T * T * 0.0000000000009);

    float A = clamp((L - 1.0) / (-1.4), 0.0, 1.0);
    float P = pow(A * A * (3.0 - 2.0 * A), 8.0) * H;

    vec3 C = exp(-vec3(10.448, 19.435, 37.188) * P);
    C *= lightRadiance;

    vec3 S = C * sunpow;
    vec3 TS = S * 16.0 + 0.01;
    float dotProduct = (TS.x) * 0.299 + (TS.y) * 0.587 + (TS.z) * 0.114;

    vec3 RC = mix(vec3(0.4, 0.5, 0.6), vec3(0.016, 0.05, 0.066), (1 - nightblend5));
    vec3 NC = vec3(0.04, 0.1, 0.11);

    S = mix(S, dotProduct * NC, (1 - nightblend5));
    S = mix(S, dotProduct * RC, rainStrength);

    return S;
}

vec3 GetAtmosphere10(vec3 rayDir)
{
    vec3 transmitance = vec3(0.0);

    return fogAtmosphere2(rayDir, 3.402823466e38, 1.0, transmitance);
}
vec3 GetAtmosphere11(vec3 rayDir)
{
    vec3 transmitance = vec3(0.0);

    return fogAtmosphere3(rayDir);
}
