
// Rayleigh and Mie constants
#define SR1_R 2.901e-6
#define SR1_G 6.779e-6
#define SR1_B 1.655e-5
#define SM_RGB 7.992e-6

// Sunlight attenuation
#define SL_R 10.448
#define SL_G 19.435
#define SL_B 37.188

// Transmittance coefficients
#define TC_R 7.836e-6
#define TC_G 1.457625e-5
#define TC_B 2.7891e-5

// Grayscale luminance weights
#define LUMA_R 0.299
#define LUMA_G 0.587
#define LUMA_B 0.114

// Precomputed atmosphere values
#define EARTH_RADIUS 6371000.0
#define T2_QUAD_COEFF 4.0589641e13
#define T2_CONST_TERM 1.2842e12
#define H_EXP 9e-13
#define PR_COEFF 0.12
#define PM_COEFF 0.2775
#define PM_DIVISOR 12.5664

// Default night/fog tint values
#define FOG_COLOR_DAY vec3(0.4, 0.5, 0.6)
#define FOG_COLOR_NIGHT vec3(0.016, 0.05, 0.066)
#define TRANS_COLOR_DAY vec3(0.8, 0.85, 0.9)
#define TRANS_COLOR_NIGHT vec3(0.3, 0.34, 0.36)
#define NIGHT_COLOR vec3(0.04, 0.1, 0.11)

vec3 fogAtmosphereALT2(
    vec3 rayDir,
    float rayL,
    float rayL2,
    inout vec3 transmittance,
    float fogFactor,
    float shadow,
    float depthshadow)
{
    // Constants
#ifdef VANILLA_SKY_COLOR
    vec3 SR = mix(pow(skyColor.rgb, vec3(3.0)) * 0.00003, vec3(2.901e-6, 6.779e-6, 1.655e-5), 0.0);
#else
    vec3 SR = vec3(2.901e-6, 6.779e-6, 1.655e-5);
#endif

    vec3 SM = vec3(7.992e-6);
    vec3 SL = vec3(10.448, 19.435, 37.188);
    vec3 TC = vec3(7.836e-6, 1.457625e-5, 2.7891e-5);
    vec3 GRAY = vec3(0.299, 0.587, 0.114);

// Light properties
#ifdef END
    const float LR = 0.001;
    const vec3 LP = vec3(0.0, 1.0, 0.0);
#elif defined NETHER
    const float LR = 0.5;
    const vec3 LP = vec3(0.0, 1.0, 0.0);
#else
    float LR = lightRadiance;
    vec3 LP = lightPos;
#endif

    rayDir = normalize(rayDir);

    // Precomputed constants
    float rdY = rayDir.y;
    float t2 = -6371000.0 * rdY + sqrt(4.0589641e13 * rdY * rdY + 1.2842e12);

    float CT = dot(rayDir, LP);
    float PR = 0.12 * (1.0 + CT * CT);
    float term = 1.7225 - 1.7 * CT;

    float OD_x = min(rayL, t2);
    float OD_y = min(rayL2, t2);

    float h = 1.0 - 1.0 / (2.0 + t2 * t2 * 9e-13);
    float h2 = h * h;
    float DR = h2;
    float DM = h2 * h2 * h * rainStrengthInv;
    float PM = 0.2775 / (12.5664 * sqrt(term) * term) * 0.5;

    float ti = clamp((LP.y - 1.0) * -0.7142857, 0.0, 1.0);
    float tSmooth = ti * ti * (3.0 - 2.0 * ti);
    float LPS = pow(tSmooth, 8.0) * h * SunsetMult;

    vec3 LC = LR * exp(-SL * LPS);
    LC = max(LC, 0.0);

    // Exponentials
    vec3 e_SR = exp(-OD_x * DR * SR);
    vec3 e_SM = exp(-OD_x * DM * SM);

    // Scattering
    vec3 S = ((1.0 - e_SR) * PR * LC * shadow + (1.0 - e_SM) * PM * LC * shadow) * sunpow;
    transmittance = exp(-OD_y * DR * TC);
    S = max(S, 0.001);

#ifdef OVERWORLD
    vec3 RTC = mix(vec3(0.8, 0.85, 0.9), vec3(0.3, 0.34, 0.36), 1.0 - nightblend5);
    vec3 RC = mix(vec3(0.4, 0.5, 0.6), vec3(0.016, 0.05, 0.066), 1.0 - nightblend5);

    if (fogFactor > 0.0)
    {

        float density2 = fogFactor * 64.0 * 100000.0;

    #ifdef VL_SELF_SHADOWING
        LC *= clamp(pow(depthshadow, 32), 0, 1);
    #endif

        // 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 = (R2 + M2) * sunpow;
        vec3 transmittance2 = exp(-t2 * DR * vec3(0.000007836, 0.00001457625, 0.000027891));

        /////
        float term = 1.85 - 1.70 * CT;

        float rayL3 = rayL + density2;
        float t2 = -6371000.0 * rdY + sqrt(4.0589641e13 * rdY * rdY + 1.2842e12);
        float PR = 0.12 * (1.0 + CT * CT);

        float OD_x = min(rayL3, t2);

        float h = 1.0 - 1.0 / (2.0 + t2 * t2 * 9e-13);
        float h2 = h * h;
        float DR = h2;
        float DM = h2 * h2 * h * rainStrengthInv; // h^5 * rainStrengthInv
        float PM = 0.2775 / (12.5664 * sqrt(term) * term) * 0.5;

        float ti = clamp((LP.y - 1.0) * -0.7142857, 0.0, 1.0); // Equivalent to (LP.y -1)/-1.4
        float tSmooth = ti * ti * (3.0 - 2.0 * ti);
        float LPS = pow(tSmooth, 8.0) * h * SunsetMult;

        vec3 LC = LR * exp(-SL * LPS);

        // Exponentials
        vec3 e_SR = exp(-OD_x * DR * SR);
        vec3 e_SM = exp(-OD_x * DM * SM);
        float shadows = mix(shadow, 1.0, 0.25);
        // Scattering
        S = ((1.0 - e_SR) * PR * LC * shadows + (1.0 - e_SM) * PM * LC * shadow * 1.0) * sunpow;
        S = mix(S, S2, fogFactor);

        transmittance = exp(-OD_x * DR * TC);
        transmittance = luma(transmittance) * RTC;

        transmittance = mix(transmittance, transmittance2, fogFactor);

        S *= mix(vec3(1.0, 0.8, 0.7), vec3(1.0), fogFactor);
    }

    S = mix(S, S + luma(S) * LC, clamp(sunElevation * 0.25, 0, 1));

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

    vec3 NC = vec3(0.04, 0.1, 0.11);
    S = mix(S, DP * NC, 1.0 - nightblend5);
    S = mix(S, DP2 * RC, rainStrength * nightblend5);
    // transmittance = luma(transmittance) * RTC;
    transmittance = mix(transmittance, luma(transmittance) * RTC, rainStrength * nightblend5);

#else

    #ifdef END
    S *= 64.0;
    S = luma(S) * sunLight;
    transmittance = exp(-OD_y * DR * (1.0 - vec3(0.184, 0.169, 0.212)) / 20000.0) + exp(-OD_y * DR * TC) * 0.2;

    if (fogFactor > 0.0)
    {
        #ifdef VL_SELF_SHADOWING
        LC *= clamp(pow(depthshadow, 64), 0, 1);
        #endif
        vec3 e_SR_t2 = exp(-t2 * DR * SR);
        vec3 e_SM_t2 = exp(-t2 * DR * SM);
        vec3 S2 = (0.5 * (1.0 - e_SR_t2) * PR * LC + (1.0 - e_SM_t2) * PM * LC) * sunpow;
        /////

        float rdY = rayDir.y;
        float t2 = rdY;

        float h = 1.0 - 1.0 / (2.0 + t2 * t2 * 9e-13);
        float h2 = h * h;
        float DR = h2;

        transmittance = mix(transmittance, exp(-t2 * DR * TC), fogFactor);

        S = mix(S, S + luma(S2) * vec3(1, 0.3, 0.2) * 2048, fogFactor);
    }

    #else
    transmittance = vec3(transmittance.x * transmittance.y * transmittance.z);
    S = luma(S) * sunLight * 0.5;

    if (fogFactor > 0.0)
    {
        #ifdef VL_SELF_SHADOWING
        LC *= clamp(pow(depthshadow, 1), 0, 1) * 4.0;
        #endif
        vec3 e_SR_t2 = exp(-t2 * DR * SR);
        vec3 e_SM_t2 = exp(-t2 * DR * SM);
        vec3 S2 = (0.5 * (1.0 - e_SR_t2) * PR * LC + (1.0 - e_SM_t2) * PM * LC) * sunpow;
        /////

        float rdY = rayDir.y;
        float t2 = rdY;

        float h = 1.0 - 1.0 / (2.0 + t2 * t2 * 9e-13);
        float h2 = h * h;
        float DR = h2;

        transmittance = mix(transmittance, exp(-t2 * DR * TC), clamp(fogFactor, 0, 1));

        S = mix(S, S + luma(S2) * vec3(1, 0.3, 0.12) * 16, clamp(fogFactor, 0, 1));
    }

    #endif
#endif

    return S;
}

vec3 fogAtmosphereALT5(vec3 rayDir)
{
    // Constants
    const vec3 SR1 = vec3(2.901e-6, 6.779e-6, 1.655e-5);
#ifdef VANILLA_SKY_COLOR
    vec3 SR = mix(pow(skyColor.rgb, vec3(3.0)) * 0.00003, SR1, 0.0);
#else
    vec3 SR = SR1;
#endif
    const vec3 SM = vec3(7.992e-6, 7.992e-6, 7.99e-6);
    const vec3 SL = vec3(10.448, 19.435, 37.188);
    const vec3 GRAY = vec3(0.299, 0.587, 0.114);

// Light properties
#ifdef END
    const float LR = 0.001;
    const vec3 LP = vec3(0.0, 1.0, 0.0);
#elif defined NETHER
    const float LR = 0.5;
    const vec3 LP = vec3(0.0, 1.0, 0.0);
#else
    // Default light position if needed
    float LR = lightRadiance;
    vec3 LP = lightPos;
#endif

    rayDir = normalize(rayDir);

    // Precomputed constants
    float rdY = rayDir.y;
    float t2 = -6371000.0 * rdY + sqrt(4.0589641e13 * rdY * rdY + 1.2842e12);

    float CT = dot(rayDir, LP);
    float PR = 0.12 * (1.0 + CT * CT);
    float term = 1.7225 - 1.7 * CT;

    float h = 1.0 - 1.0 / (2.0 + t2 * t2 * 9e-13);
    float h2 = h * h;
    float DR = h2;
    float DM = h2 * h2 * h * rainStrengthInv; // h^5 * rainStrengthInv
    float PM = 0.2775 / (12.5664 * sqrt(term) * term) * 0.5;

    float ti = clamp((LP.y - 1.0) * -0.7142857, 0.0, 1.0);
    float tSmooth = ti * ti * (3.0 - 2.0 * ti);
    float LPS = pow(tSmooth, 8.0) * h * SunsetMult;

    vec3 LC = LR * exp(-SL * LPS);

    // Exponentials
    vec3 e_SR = exp(-t2 * DR * SR);
    vec3 e_SM = exp(-t2 * DM * SM);

    // Scattering
    vec3 S = ((1.0 - e_SR) * PR * LC + (1.0 - e_SM) * PM * LC) * sunpow;

#ifdef OVERWORLD

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

    vec3 RC = mix(vec3(0.4, 0.5, 0.6), vec3(0.016, 0.05, 0.066), 1.0 - nightblend5);
    vec3 NC = vec3(0.04, 0.1, 0.11);
    S = mix(S, DP * NC, 1.0 - nightblend5);
    S = mix(S, DP2 * RC, rainStrength * nightblend5);

#else

    #ifdef END
    S *= 64.0;
    S = luma(S) * sunLight;

    #else
    S = luma(S) * sunLight * 0.5;
    S = mix(S, S + luma(S) * vec3(1, 0.3, 0.12) * 16, 0.1);

        //   transmittance *= 2.0;
    #endif
#endif

    return S;
}
vec3 fogAtmosphereALT3(vec3 rayDir)
{
    vec3 transmittance = vec3(0.0);
    return fogAtmosphereALT2(rayDir, 3.402823466e38, 3.402823466e38, transmittance, 0.0, 1.0, 1.0);
}
