#version 330

layout( location = 0 ) in vec3 InVertex;
layout( location = 1 ) in vec3 InNormal;
/*
out vec3 vNormal;
out vec3 vEye;
out vec4 vPos;
*/

out vec2 vTexCoords;
out vec3 vRColor;
out vec3 vMColor;
out vec3 vDirection;
out vec3 vSunDir;

uniform mat4 uViewMatrix;
uniform mat4 uProjectionMatrix;
uniform mat4 uModelMatrix;
uniform vec3 uSunPosition;
uniform float uRadius;

float ScaleFunc( float inCos )
{
	float scaleDepth = 0.25;
	float x = 1.0 - inCos;
	return scaleDepth * exp( -0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
}

void main()
{
	float domeHeight = InVertex.y / uRadius;
	vec2 normalizedPos = ( InVertex.xz / uRadius ) * ( 1.0 - domeHeight + 0.5 );
	vTexCoords = ( normalizedPos * 0.5 + 0.5 );
	
	float innerRadius = 10.0;
	float outerRadius = 10.25;
	float planetaryScale = 1.0 / ( outerRadius - innerRadius );
	vec3 wavelengths = 1.0 / pow( vec3( 0.650, 0.570, 0.475 ), vec3( 4.0 ) );
	float Kr4PI = 0.0025 * 4.0 * 3.14;
	float Km4PI = 0.0010 * 4.0 * 3.14;
	float KESun = 20.0;
	float scaleDepth = 0.25;
	float KrESun = 0.0025 * KESun;
	float KmESun = 0.0010 * KESun;
	vec3 cameraPos = -( uViewMatrix * uModelMatrix * vec4( InVertex, 1.0 ) ).xyz;
	vec3 vertexPos = ( uModelMatrix * vec4( InVertex, 1.0 ) ).xyz;
	float cameraHeight = length( cameraPos );
	vSunDir = normalize( uSunPosition - vertexPos );
	vec3 ray = vertexPos - cameraPos;
	float rayLength = length( ray );
	ray /= rayLength;
	
	// Raymarching
	vec3 startPos = cameraPos;
	float height = length( startPos );
	float depth = exp( planetaryScale / scaleDepth * ( innerRadius - cameraHeight ) );
	float startAngle = dot( ray, startPos ) / height;
	float startOffset = depth * ScaleFunc( startAngle );
	
	float sampleCount = 2.0;
	float sampleLength = rayLength / sampleCount;
	float scaledLength = sampleLength * planetaryScale;
	vec3 sampleRay = ray * sampleLength;
	vec3 samplePos = startPos + sampleRay * 0.5;
	
	vec3 skyColor = vec3( 0.0 );
	for( int i = 0; i < sampleCount; ++i )
	{
		float sampleHeight = length( samplePos );
		float sampleDepth = exp( planetaryScale / scaleDepth * ( innerRadius - sampleHeight ) );
		float lightAngle = dot( vSunDir, samplePos ) / sampleHeight;
		float cameraAngle = dot( ray, samplePos ) / sampleHeight;
		float scatter = ( startOffset + sampleDepth * ( ScaleFunc( lightAngle ) - ScaleFunc( cameraAngle ) ) );
		vec3 attenuate = exp( -scatter * ( wavelengths * Kr4PI + Km4PI ) );
		skyColor += attenuate * ( sampleDepth * scaledLength );
		samplePos += sampleRay;
	}
	
	vRColor = skyColor * ( wavelengths * KrESun );
	vMColor = skyColor * KmESun;
	vDirection = cameraPos - vertexPos;
	
	/*
	vEye = vec3( ( uModelMatrix ) * vec4( InVertex, 1.0 ) );
	vNormal = -normalize( transpose( inverse( mat3( uViewMatrix * uModelMatrix ) ) ) * InNormal );
	vPos = ( uModelMatrix * vec4( InVertex, 1.0 ) );
	vLightPos = ( uViewMatrix * uModelMatrix * vec4( uLightPos, 1.0 ) );
	*/
	
	gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * vec4( InVertex, 1.0 );
}