
// ------- ATTRIBUTES (VERTEX BUFFER DATA) -------
attribute vec4		a_vPosition0;

// ------- UNIFORMS (SHADER CONSTS) -------
uniform mat4		hu_mPMVMatrix;
uniform vec3		hu_vCameraPos;
uniform vec3		u_vNormalizedLightDir;
uniform float		u_fGlobeRadius;
uniform float		u_fAtmosphereRadius;

// ------- INTERPOLATORS (SHADER OUTPUTS) -------
varying vec3		v_vNormal;
varying float		v_fAlpha;

void main(void)
{
	gl_Position = hu_mPMVMatrix*a_vPosition0;

    vec3 position = a_vPosition0.xyz;
    vec3 camPos = hu_vCameraPos;
 
	float radius = length(position);
    float radius2 = radius*radius; 
    float camHeight = length(camPos);
    vec3 camToPos = position - camPos;
    float farDist = length(camToPos);
 
	vec3 lightDir = -u_vNormalizedLightDir;
    vec3 normal = normalize(position);
 
    vec3 rayDir = camToPos/farDist;
    float camHeight2 = camHeight*camHeight;
 
    // Calculate the closest intersection of the ray with the outer atmosphere
    float B = 2.0 * dot(camPos, rayDir);
    float C = camHeight2 - radius2;
    float det = max(0.0, B*B - 4.0*C);
    float nearDist = 0.5*(-B - sqrt(det));
    vec3 nearPos = camPos + (rayDir*nearDist);
    vec3 nearNormal = normalize(nearPos);

    // get dot products we need
    float lc = dot(lightDir, camPos/camHeight);
    float ln = dot(lightDir, normal);
    float lnn = dot(lightDir, nearNormal);

    // get distance to surface horizon
    float altitude = camHeight - u_fGlobeRadius;
    float horizonDist = sqrt((altitude*altitude) + (2.0*u_fGlobeRadius*altitude));
    float maxDot = horizonDist / camHeight;
 
    // get distance to atmosphere horizon - use max(0,...) because we can go into the atmosphere
    altitude = max(0, camHeight - u_fAtmosphereRadius);
    horizonDist = sqrt((altitude*altitude) + (2.0*u_fAtmosphereRadius*altitude));
 
    // without this, the shift between inside and outside atmosphere is  jarring
    //float tweakAmount = 0.1;
    //float minDot = max(tweakAmount,horizonDist / camHeight);
	float minDot = horizonDist/camHeight;
 
    // scale minDot from 0 to -1 as we enter the atmosphere
    //float minDot2 = ((camHeight - u_fGlobeRadius) * (1.0 / (u_fAtmosphereRadius  - u_fGlobeRadius))) - (1.0 - tweakAmount);
    //minDot = min(minDot, minDot2);
  
    // get dot product of the vertex we're looking out
    float posDot = dot(camToPos/farDist, -camPos/camHeight) - minDot;
 
    // calculate the height from surface in range 0..1
    float height = posDot*(1.0/(maxDot - minDot));
 
    // push the horizon back based on artistic taste
	const float StretchAmt = 0.25;
    ln = max(0,ln + StretchAmt);
    lnn = max(0,lnn + StretchAmt);

    // the front color is the sum of the near and far normals
    float brightness = saturate(ln + (lnn*lc));
 
    // use "saturate(lc + 1.0 + StretchAmt)" to make more of the sunset side color be used when behind the planet
    //v_vTex0UV.x = brightness * saturate(lc + 1.0 + StretchAmt);
    //v_vTex0UV.y = height;
 
    // as the camera gets lower in the atmosphere artificially increase the height
    // so that the alpha value gets raised and multiply the increase amount
    // by the dot product of the light and the vertex normal so that 
    // vertices closer to the sun are less transparent than vertices far from the sun.
    //height -= min(0.0,minDot2 + (ln * minDot2));
    v_fAlpha = height*brightness;
 
    // normalised camera to position ray
    //oCamToPos = -rayDir;
 
    //oLightDir = normalize(lightPos.xyz - position.xyz); 
}
