////////////////////////////////////////////////
//
// sky shaders
//
////////////////////////////////////////////////

shader 0 "skybox" [
    attribute vec4 vvertex, vcolor;
    attribute vec2 vtexcoord0;
    uniform mat4 skymatrix;
    uniform float ldrscale;
    varying vec4 colorscale;
    varying vec2 texcoord0;
    void main(void)
    {
        gl_Position = skymatrix * vvertex;
        texcoord0 = vtexcoord0; 
        colorscale = vec4(ldrscale * vcolor.rgb, vcolor.a);
    }
] [
    uniform sampler2D tex0;
    varying vec4 colorscale;
    varying vec2 texcoord0;
    fragdata(0) vec4 fragcolor;
    void main(void)
    {
        vec4 color = texture2D(tex0, texcoord0);
        fragcolor = colorscale * color;
    }
]

shader 0 "skyboxoverbright" [
    attribute vec4 vvertex, vcolor;
    attribute vec2 vtexcoord0;
    uniform mat4 skymatrix;
    uniform float ldrscale;
    varying vec4 colorscale;
    varying vec2 texcoord0;
    void main(void)
    {
        gl_Position = skymatrix * vvertex;
        texcoord0 = vtexcoord0; 
        colorscale = vec4(ldrscale * vcolor.rgb, vcolor.a);
    }
] [
    uniform sampler2D tex0;
    uniform vec3 overbrightparams;
    uniform float ldrscale;
    varying vec4 colorscale;
    varying vec2 texcoord0;
    fragdata(0) vec4 fragcolor;
    void main(void)
    {
        vec4 color = texture2D(tex0, texcoord0);
        float lum = dot(vec3(@lumweights), color.rgb);
        float overbright = mix(overbrightparams.x, overbrightparams.y, clamp(lum - overbrightparams.z, 0.0, 1.0));
        color.rgb *= overbright;
        fragcolor = colorscale * color;
    }
]

shader 0 "atmosphere" [
    attribute vec4 vvertex;
    uniform mat4 sunmatrix;
    varying vec3 camvec;
    void main(void)
    {
        gl_Position = vvertex;

        vec4 p = sunmatrix * vvertex;
        camvec = p.xyz / p.w;
    }
] [
    // adapted from http://blog.cloudparty.com/2013/09/25/stunning-procedural-skies-in-webgl-part-2/
    uniform vec3 sunlight;
    uniform vec3 sundir;
    uniform vec3 sundiskparams;
    uniform vec3 atmoradius;
    uniform float gm;
    uniform vec3 betar, betam, betarm;
    uniform vec2 hdrgamma;
    uniform float atmoalpha;
    varying vec3 camvec;
    fragdata(0) vec4 fragcolor;

    vec3 calcextinction(float dist)
    {
        return exp2(-dist * betarm);
    }

    vec3 calcscatter(float costheta)
    {
        float rphase = 1.0 + costheta*costheta;
        float mphase = pow(1.0 + gm*(gm - 2.0*costheta), -1.5);
        return betar*rphase + betam*mphase;
    }

    float baseopticaldepth(vec3 ray)
    {
        float a = atmoradius.x * max(ray.z, min(sundir.z, 0.0));
        return sqrt(a*a + atmoradius.z) - a;
    }

    float opticaldepth(vec3 pos, vec3 ray)
    {
        pos.z = max(pos.z, 0.0) + atmoradius.x;
        float a = dot(pos, ray);
        return sqrt(a*a + atmoradius.y - dot(pos, pos)) - a;
    }

    void main(void)
    {
        vec3 camdir = normalize(camvec);
        float costheta = dot(camdir, sundir);

        // optical depth along view ray
        float raydist = baseopticaldepth(camdir);

        // extinction of light along view ray
        vec3 extinction = calcextinction(raydist);

        // optical depth for incoming light hitting the view ray
        float lightraydist = opticaldepth(camdir * (raydist * max(0.15 + 0.75 * sundir.z, 0.0)), sundir);

        // cast a ray towards the sun and calculate the incoming extincted light
        vec3 incominglight = calcextinction(lightraydist);

        // calculate the in-scattering
        vec3 scattering = calcscatter(costheta) * (1.0 - extinction);

        // combine
        vec3 inscatter = incominglight * scattering;

        // sun disk
        vec3 sundisk = sundiskparams.z * extinction * pow(clamp(costheta*sundiskparams.x + sundiskparams.y, 0.0, 1.0), 8.0);

        inscatter += sundisk; 
        @(hdrgammaencode inscatter)

        fragcolor = vec4(sunlight * inscatter, atmoalpha);
    }
]

shader 0 "skyfog" [
    attribute vec4 vvertex, vcolor;
    uniform mat4 skymatrix;
    uniform float ldrscale;
    varying vec4 color;
    void main(void)
    {
        gl_Position = skymatrix * vvertex;
        color = vec4(ldrscale * vcolor.rgb, vcolor.a);
    }
] [
    uniform sampler2D tex0;
    varying vec4 color;
    fragdata(0) vec4 fragcolor;
    void main(void)
    {
        fragcolor = color;
    }
]

