uniform vec3 skyColor;

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 + vec2(0.01, 0)).rgb;
}

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

    float ssR = alpha;
    float sin_v, cos_v;

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

    return vec2(cos_v, sin_v) * ssR;
}

uniform float lightSign0;
uniform vec4 lightCol0;
uniform float skyIntensityNight;

float luma2(vec3 color) {
    return dot(color, vec3(0.299, 0.587, 0.114));
}

vec3 toLinear2(vec3 sRGB) {
    return sRGB * (sRGB * (sRGB * 0.305306011 + 0.682171111) + 0.012522878);
}
const vec3 totalCoeff = vec3(4.9625031e-12, 1.1760478e-11, 2.0493143e-11);
const float ln2 = 0.69314718055994530941723212145818;

vec3 scatter(vec3 coeff, float depth) {
    return coeff * depth;
}
vec3 absorb(vec3 coeff, float depth) {
    return exp2(scatter(coeff, -depth));
}
float calcParticleThickness(float depth) {
    depth = max(depth + 0.01, 0.01);
    depth = depth * depth * (3.0 - 2.0 * depth);
    return 5000000000.0 / depth;
}
float calcParticleThickness0(float depth) {
    depth = max(depth + 0.25, 0.25);
    depth = depth * depth * (3.0 - 2.0 * depth);
    return 5000000000.0 / depth;
}
float rayleighPhase(float plp) {
	return 0.375 * (1.0 + pow(1.0 - plp, 2.0));
}


vec3 calcAtmosphericScatter(vec3 p, vec3 lp) {

#ifdef WATER_PROG
    if (p.y < 0.0)
        p.y = -p.y;
#endif
    float plp = distance(p, lp);
    float opticalDepth = calcParticleThickness(p.y);
    float opticalDepthLight = calcParticleThickness(lp.y);

    vec3 scatterView = scatter(totalCoeff, opticalDepth);
    vec3 absorbView = absorb(totalCoeff, opticalDepth);

    vec3 scatterLight = scatter(totalCoeff, opticalDepthLight);
    vec3 absorbLight = absorb(totalCoeff, opticalDepthLight);

    vec3 absorbSun = abs(absorbLight - absorbView) / (abs((scatterLight - scatterView) * ln2) + 1e-8);
    vec3 scatterSun = scatterView * rayleighPhase(plp);

    vec3 sunSpot = smoothstep(0.04, 0.03, plp) * absorbView * pi * 0.01;
    vec3 final = (scatterSun * absorbSun + sunSpot) * pi;
    final = mix(final, vec3(luma2(final) * vec3(0.4, 0.5, 0.6)), rainStrength);

    float lum = luma2(final);
    vec3 diff = final - lum;
    final = diff * (0.25) + final;

    return final;
}

vec3 calcAtmosphericScatter3(vec3 p, vec3 lp) {
    //p = mix(p, normalize(p), 0.5);

    float plp = distance(p, lp);
    float opticalDepth = calcParticleThickness(p.y);
    float opticalDepthLight = calcParticleThickness(lp.y);

    vec3 scatterView = scatter(totalCoeff, opticalDepth);
    vec3 absorbView = absorb(totalCoeff, opticalDepth);

    vec3 scatterLight = scatter(totalCoeff, opticalDepthLight);
    vec3 absorbLight = absorb(totalCoeff, opticalDepthLight);

    vec3 absorbSun = abs(absorbLight - absorbView) / (abs((scatterLight - scatterView) * ln2) + 1e-8);
    vec3 scatterSun = scatterView * rayleighPhase(plp);

    vec3 sunSpot = smoothstep(0.05, 0.0, distance(p, lp)) * absorbView * pi * 0.015;
    vec3 final = (scatterSun * absorbSun + sunSpot) * pi;
    final = mix(final, vec3(luma2(final) * vec3(0.4, 0.5, 0.6)), rainStrength);

    float lum = luma2(final);
    vec3 diff = final - lum;
    final = diff * (0.25) + final;

    return final * 0.33 + skyIntensityNight * 0.1 * vec3(0.08, 0.12, 0.18);
}
vec3 skyLut2(vec3 sVector, vec3 sunVec, float cosT, float rainStrength) {

    return (calcAtmosphericScatter(sVector, sunVec) * 0.33) + skyIntensityNight * 0.1 * vec3(0.08, 0.12, 0.18);

}
