

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 fogAtmosphereALT(vec3 rayDir, float rayL, float rayL2, inout vec3 transmittance, float fogFactor)
{
#ifdef END
    float lightRadiance = 0.001;
    vec3 lightPos = vec3(0.0, 1, 0);

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

#endif
    // vec3 lightPos = normalize(vec3(1, 0.2, 0.1));
    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 * SunsetMult;

    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

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

    S = (1.0 - exp(-OD.x * DR * SR)) * PR * fogColor * 0.5;

#endif
#endif

    return S;
}

vec3 fogAtmosphere2(vec3 rayDir, float rayL, float rayL2, inout vec3 transmittance)
{

    return fogAtmosphereALT(rayDir, rayL, rayL2, transmittance, 0);
}

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

    return fogAtmosphereALT(rayDir, 3.402823466e38, 1.0, transmitance, 0);
}

vec3 cosineHemisphereSample(vec2 Xi)
{
    float r = sqrt(Xi.x);
    float theta = 2.0 * PI * Xi.y;

    float x = r * cos(theta);
    float y = r * sin(theta);

    return vec3(x, y, sqrt(clamp(1.0 - Xi.x, 0., 1.)));
}
vec2 sphereToCarte(vec3 dir)
{
    float lonlat = atan(-dir.x, -dir.z);
    return vec2(lonlat * (0.5 / PI) + 0.5, 0.5 * dir.y + 0.5);
}

vec3 skyFromTex(vec3 pos, sampler2D sampler)
{
    vec2 p = sphereToCarte(pos);
    return texture(sampler, p * 0.25 - vec2(0.0005, 0.0005)).rgb;
}

vec2 tapLocation(int sampleNumber, int nb, float nbRot, float jitter)
{
    float alpha = float(sampleNumber + jitter) / nb;
    float angle = (jitter + alpha) * (nbRot * TWO_PI);

    float ssR = alpha;
    float sin_v, cos_v;

    sin_v = sin(angle);
    cos_v = cos(angle);

    return vec2(cos_v, sin_v) * ssR;
}
vec2 sincos(float x)
{
    return vec2(sin(x), cos(x));
}
