//iGlobalTime on aika
//iChannel0 on noisetekstuuri
//iChannel1 on maapallotekstuuri
uniform float iGlobalTime;
uniform vec3 iResolution;
uniform sampler2D iChannel0;
uniform sampler2D iChannel1;

uniform float u_cammode;

//iGlobalTime on aika
//iChannel0 on noisetekstuuri
//iChannel1 on maapallotekstuuri

float PI = 3.14159265;
float currentPerlin1;
float currentPerlin2;
vec2 currentId1;
vec2 currentId2;

//pöllitty!
void rX(inout vec3 p, float a) 
	{
        float c,s;
		vec3 q=p;
        c = cos(a); s = sin(a);
        p.y = c * q.y - s * q.z;
        p.z = s * q.y + c * q.z;
        //return vec3(p);
	}

//pöllitty!
void rY(inout vec3 p, float a)
	{
        float c,s;
		vec3 q=p;
        c = cos(a); s = sin(a);
        p.x = c * q.x + s * q.z;
        p.z = -s * q.x + c * q.z;
	}

//pöllitty!
void rZ(inout vec3 p, float a) 
	{
        float c,s;
		vec3 q=p;
        c = cos(a); s = sin(a);
        p.x = c * q.x - s * q.y;
        p.y = s * q.x + c * q.y;
	}

//ei pöllitty!
float perlin(vec3 p)
	{	
		/*
		vec3 i = floor(p);
        vec4 a = dot(i, vec3(1., 57., 21.)) + vec4(0., 57., 21., 78.);
        vec3 f = cos((p-i)*acos(-1.))*(-.5)+.5;
        a = mix(sin(cos(a)*a),sin(cos(1.+a)*(1.+a)), f.x);
        a.xy = mix(a.xz, a.yw, f.y);
        return mix(a.x, a.y, f.z);
		*/
		return (-1.5+3.*texture2D(iChannel0, p.z*p.xy).r);
	}

//pöllitty!
float noise(vec2 co, float tango){
	return 1.+2.*texture2D(iChannel0, tango * co.xy).r;
}

float hexagon1(vec3 o, vec2 oo, vec3 orig)
{
	//float distscale = iGlobalTime*clamp(.2*length(orig.xz),0.0,1.0);
	float h = 3.+3.*currentPerlin1;
	vec3 q = abs(o);			//pienet välit ruutujen väliin
	//q.y *= .9;						//korkeus
	//q.y+= .5*sin(iGlobalTime+length(oo));
	q.y *= 1.-.1*sin(q.y+h+1.5*iGlobalTime);
	return (max(q.y-h,max(q.x+q.z*0.57735,q.z*1.1547)));
}

float hexagon2(vec3 o, vec2 oo, vec3 orig)
{
	//float distscale = iGlobalTime*clamp(.2*length(orig.xz),0.0,1.0);
	float h = 3.+3.*currentPerlin2;
	vec3 q = abs(o);			//pienet välit ruutujen väliin
	//q.y *= .9;						//korkeus
	//q.y+= .5*sin(iGlobalTime+length(oo));
	q.y *= 1.-.1*sin(q.y+h+1.5*iGlobalTime);
	return (max(q.y-h,max(q.x+q.z*0.57735,q.z*1.1547)));
}

float hexabon(vec3 o, vec3 oo, vec3 orig)
{
	float r = 10.;	//tähän joku tarpeeks kaukainen :I
	//keskipylväs
	if (length(oo.xz) < 6.)	
	{
		oo.xz*=.15+sin(oo.y*.16);
		oo.x += -.9+(.75*cos(.7*oo.y-14.)*((oo.y-4.)/4.));
		oo.z += .7+(.75*sin(oo.y-14.)*((oo.y-4.)/4.));
		//oo *= 1.+.15*perlin(2.*oo);
		oo.xz *= .6+.2*(-1.+noise(vec2(o.x+o.z,o.y),.2));
		r = (max(oo.y - 12.,length(oo.xz)));
	} 
	return (r);
}

// polynomial smooth min (k = 0.1);
float smin( float a, float b, float k )
{
    float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
    return mix( b, a, h ) - k*h*(1.0-h);
}

vec4 b(vec3 o)
	{

   float pi = 3.14159265;
	
	float id = 0.;
	
	//xz plane on vaakataso, y on pystyakseli

	/* KAMERA-ASETUKSET */

	if (u_cammode < 0.5)
	{
	//alkuperäinen kamera


	rX(o,-PI/12.);
	rZ(o,length(o)*.01);
	o.x += 4.;
    o.y+=10.;

}
else if (u_cammode < 1.5)

{

	//herkästi alaviistosta
	
	o.x-=7.;
	o.z+=10.;
    o.y+=5.;
	rX(o,-PI/4.);
	rZ(o,length(o)*.01);
}

else
{
	//maapallo isona keskellä
	

	rZ(o,length(o)*.01);
	o.y+=16.;
}
	
	//kamera kiertää maapalloa
	
   	float timescale = .35;//.25
	
	rY(o,-pi/2.+-timescale*iGlobalTime);


	vec3 oksu = o;
	
	o.x += 8.*cos(timescale*iGlobalTime); 
	o.z += 8.*sin(timescale*iGlobalTime);

	vec3 oo = o;
	vec3 orig = o;
	vec3 globo = vec3(o.x,o.y-18.,o.z);
	
    //uv-koordinaatin laskentaan
	float phi = atan(globo.z,globo.x)/(2.*pi);
    float roo = acos(globo.y / length(globo))/pi;
	float col = texture2D(iChannel1, vec2(phi, roo)).a;
	
	
	//maapallo
	float m3 = (length(globo)-6.);
	
	//heksatolpat
	o.x = -5./3.+mod(o.x, 10./3.);
    o.z = -1.+mod(o.z, 2.);
 	orig.x+=0.;
	orig.x = floor(orig.x/(10./3.));
	orig.z = floor(orig.z/2.);
	
	if (orig.xz != currentId1)
	{
		currentId1 = orig.xz;
		float distscale = 1.-clamp(.01*length(orig.xz),0.0,0.1);
		currentPerlin1 = perlin(vec3(orig.xz,distscale));
		//currentPerlin1 = perlin(vec3(orig.xz*.8+.21*distscale,.1*distscale));
		//id = 2.;	//debug
	}
	
	//maksimi piirtoetäisyys
	float m=2.;
	if (length(orig.xz) > .3 && orig.y < 8.) m = min(m,hexagon1(o,oo.xz,orig));
	
	//toinen rivi heksatolppia
	o=oo;
	orig=oo;
	o.x+=5./3.;
	o.z+=1.;
	o.x = -5./3.+mod(o.x , 10./3.);
    o.z = -1.+mod(o.z , 2.);
	orig.x+=5./3.;
	orig.z+=1.;
	orig.x = .5+floor(orig.x/(10./3.));
	orig.z = .5+floor(orig.z/2.);

	if (orig.xz != currentId2)
	{
		currentId2 = orig.xz;
		float distscale = 1.-clamp(.01*length(orig.xz),0.0,0.1);
		currentPerlin2 = perlin(vec3(orig.xz,distscale));
		//currentPerlin2 = perlin(vec3(orig.xz*.8+.21*distscale,.1*distscale));
		//id = 2.;	//debug
	}
	
	float m2=2.;
	if (length(orig.xz) > .3 && orig.y < 8.) m2 = hexagon2(o,oo.xz,orig);

	//maapallon varsi
	if (length(oo.xz) < 4. && oo.y < 11.2) m2 = smin(m2,hexabon(o,oo,orig),.5);
	//varren alla oleva möhkäle
	//m2 = smin(m2,log((1.+.1*perlin(oo))*length(vec3(oo.x*.5,oo.y,oo.z*.5))-4.),1.);
	if (length(oo.xz) < 12. && oo.y < 7.) m2 = smin(m2,log((1.+.1*noise(vec2(oo.x,32.*phi+sin(1.5*length(oo.xz))),.1))*length(vec3(oo.x*.5,oo.y,oo.z*.5))-4.),1.);
	
	//maapallo paikoilleen
	oo.y -= 18.;
	
	m=min(m,m2);

	//maapallon materiaalit ja kohoavat mantereet
	if (col > .0 && length(oo) < 8.) 
	{
		id = 1.;
		m = smin(m,(1.-col*.15)*m3,1.);
	} 
	else if (col < .1 && length(oo) < 8.)
	{
		 id = 2.;
		 m = smin(m,m3,1.);
	}

	//varren gradientti
	if (length(oo.xz) < 3.2 && oo.y < -7.5)
	{
		//id = clamp(.5*perlin(2.*oo)+o.y*.5-3.4,0.,1.);
		id = clamp(.5*noise(vec2(32.*roo,o.y),.75)+o.y*.5-4.6,0.,1.);
	}
	
	//lentopallukat
	oksu*=.07;
	oksu*= noise(.1*oo.xz,.01);
	oksu.y-=.2*iGlobalTime;
	
	oksu = -1.+mod(oksu,2.);
	if (length(oksu) < .05) 
	{
		m = min(m,length(oksu));	
		id = 0.;
	}
	
	//tyhmät taikavakiot että näyttää kivalta
	m = 14.*log(m);
	
    return vec4(m,id,phi,roo);
}

vec3 rm(vec3 p)	
{
	float fov = pow(.7*length(p.xy),2.);
	vec3 d=1.*vec3(p.x,p.y,.5-1.*fov)/(8.*512.);
	vec3 q=p;

	float l;
	float x=0.;
	vec4 result;
	 
	for (int i=0;i<64;i++)
	{
		result = b(p);
		l=result.x;
		p+=(512.+x)*l*d;
		x+=.01;
		if (l<.25) break;	
	}
	
	//maapallon diffuse map
	vec3 col = texture2D(iChannel1, result.zw).rgb;
	
	//maapallon diffusen ja heksapalkkien värisiirtymä
	if (result.y <= 1.) col = mix(vec3(.4,.3,.3),col,result.y);
	
	//noisejutut maapalloon
	float vatkaus = (-5. + mod(iGlobalTime+tan(iGlobalTime),6.5));
	float tango = tan(2.33*iGlobalTime);
	tango = clamp (tango,0.0,1.0);
	if (vatkaus > 1.) 
	{ 
		vatkaus = 1.5-vatkaus;
		vatkaus *= 8.*vatkaus;
	} 	else vatkaus = 0.;
	
	if (result.y == 2.) col = noise(p.xy, vatkaus)*abs((tango+.2*+vatkaus)*.1*sin(vatkaus*sin(-p.x+p.y +iGlobalTime)+ p.x+p.y+6.*iGlobalTime))+vec3(.2,.3,.5);
	
	//maapallossa lähempi kirkkaampi, muualla kauempi kirkkaampi
	x = mix(x*x,.32-x,result.y);
	
	col = mix(col,q,.15);
	return (col*(16.*x)+.02*vec3(length(p)));
 }

void main()
{
	vec2 p = -1.0 + 2.0 * vec2(gl_FragCoord.x-0.,gl_FragCoord.y+80.) / iResolution.xy;
	p.x *= iResolution.z;
	vec3 o= vec3(p.x,p.y,-1.0);				//säteen suunta 
    gl_FragColor = vec4(rm(o)/4.,1.0);		//tyhmä jakolasku
 //   gl_FragColor = vec4(perlin(vec3(p * 10.0, 0.0)));
 //	gl_FragColor = texture2D(iChannel0, gl_FragCoord.xy / iResolution.xy);
}
