#version 330 core

uniform float time;
uniform vec2 resolution;
uniform vec2 wPos;
uniform vec2 wRad;

in vec2 mypos;
out vec4 fragColor;




#define FLATTEN .5
#define NUM_STEPS 50

vec3 sunColour = vec3(1.0, .86, .7);

#define cloudLower 2400.0
#define cloudUpper 3800.0

float gTime;
float cloudy;
vec2 add = vec2(1.0, 0.0);
#define MOD3 vec3(3.07965, 7.1235, 4.998784)

float Hash(vec3 p)
{
	p  = fract(p /  MOD3);
    p += dot(p.xyz, p.yzx + 19.19);
    return fract(p.x * p.y * p.z);
}

float Noise(in vec3 p)
{
    vec3 i = floor(p);
	vec3 f = fract(p); 
	f *= f * (3.0-2.0*f);

    return mix(
		mix(mix(Hash(i  			), 	Hash(i + add.xyy),f.x),
			mix(Hash(i + add.yxy),		Hash(i + add.xxy),f.x),
			f.y),
		mix(mix(Hash(i + add.yyx),    	Hash(i + add.xyx),f.x),
			mix(Hash(i + add.yxx), 		Hash(i + add.xxx),f.x),
			f.y),
		f.z);
}

float FBM( vec3 p )
{
	p *= .5;
    float f;
    f  = 0.5000   * Noise(p); p =  p * 3.02;
    f += 0.2500   * Noise(p); p =  p * 3.03;
    f += 0.1250   * Noise(p); p =  p * 3.01;
    f += 0.0625   * Noise(p); p =  p * 3.03;
	f += 0.03125  * Noise(p); p =  p * 3.02;
	f += 0.015625 * Noise(p);
    return f;
}

float Map(vec3 p)
{
	float h = FBM(p);
	return h-cloudy-.42;
}


//--------------------------------------------------------------------------
// Grab all sky information for a given ray from camera
vec3 GetSky(in vec3 pos,in vec3 rd)
{
	vec2 mouse=wPos/wRad;
	float dayTime = mouse.y;
    	vec3 sunPos = normalize( vec3(  (dayTime)-.5, 0.22,  0.0 ) );
	float sunAmount = max( dot( rd, sunPos), 0.0 );
	// Do the blue and sun...	
	vec3  sky = mix(vec3(.1, .1, .4), vec3(.1, .45, .7), 1.0-pow(abs(rd.y), .5));
	sky = sky + sunColour * min(pow(sunAmount, 1500.0) * 2.0, 1.0);
	sky = sky + sunColour * min(pow(sunAmount, 10.0) * .75, 1.0);
	
	// Find the start and end of the cloud layer...
	float beg = ((cloudLower-pos.y)/rd.y);
	float end = ((cloudUpper-pos.y)/rd.y);
	// Start position...
	vec3 p = vec3(pos.x + rd.x * beg, cloudLower, pos.z + rd.z * beg);

	// Trace clouds through that layer...
	float d = 0.0;
	float add = (end-beg) / float(NUM_STEPS);
	vec4 sum = vec4(0.1, .1, .1, 0.0);
	// Horizon fog is just thicker clouds...
	vec4 col = vec4(0.0, 0.0, 0.0, pow(1.0-rd.y,30.) * .2);
	for (int i = 0; i < NUM_STEPS; i++)
	{
		if (sum.a >= 1.0) continue;
		vec3 pos = p + rd * d;
		float h = Map(pos * .001);
		col.a += max(-h, 0.0) * .10; 
		col.rgb = mix(vec3((pos.y-cloudLower)/((cloudUpper-cloudLower))) * col.a, sunColour, max(.3-col.a, 0.0) * .04);
		sum = sum + col*(1.0 - sum.a);
		d += add;
	}
	sum.xyz += min((1.-sum.a) * pow(sunAmount, 3.0), 1.0);
	sky = mix(sky, sum.xyz, sum.a);

	return clamp(sky, 0.0, 1.0);
}

//--------------------------------------------------------------------------
vec3 CameraPath( float t )
{
    return vec3(4000.0 * sin(.16*t), 0.0, 4000.0 * cos(.155*t) );
}

//--------------------------------------------------------------------------
vec3 IntoSphere(vec2 uv)
{
	vec3 dir;
	uv = (-1.0 + 2.0 * uv);
	dir.x = uv.x;
	dir.z = uv.y;
	dir.y = sqrt(1.0-dir.x * dir.x  - dir.z*dir.z) * FLATTEN;
	if (length(dir) >= 1.0) return vec3(0.0, .001, .999);
	dir = normalize(dir);
	
	return dir;
}

//--------------------------------------------------------------------------
vec2 IntoCartesian(vec3 dir)
{
	vec2 uv;
	dir.y /= FLATTEN;
	dir = normalize(dir);
	uv.x = dir.x;
	uv.y = dir.z;
	uv = .5 + (.5 * uv);
	return uv;
}

void main( void ) {

	vec2 mouse=wPos/wRad;
	float m = (mouse.x)*30.0;
	gTime = time*.5 + m - 0.8;
	cloudy = cos(gTime * .27+.4) * .3;

   //vec2 uv = gl_FragCoord.xy / resolution.xy;
	vec2 uv = 0.5+0.5*(mypos-wPos)/wRad;
	
	vec3 dir = IntoSphere(uv);

	vec3 col = GetSky(CameraPath(gTime), dir);

	// Don't gamma too much to keep the moody look...
	col = pow(col, vec3(.6));
	fragColor=vec4(col, 1.0);
}


//--
//-- Copyright (C) 2020  <fastrgv@gmail.com>
//--
//-- This program is free software: you can redistribute it and/or modify
//-- it under the terms of the GNU General Public License as published by
//-- the Free Software Foundation, either version 3 of the License, or
//-- (at your option) any later version.
//--
//-- This program is distributed in the hope that it will be useful,
//-- but WITHOUT ANY WARRANTY; without even the implied warranty of
//-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//-- GNU General Public License for more details.
//--
//-- You may read the full text of the GNU General Public License
//-- at <http://www.gnu.org/licenses/>.
//--

