#version 430 core

///////////////////////////////////////////////////////////////////////////////
// shader inputs/outputs
///////////////////////////////////////////////////////////////////////////////
uniform float iGlobalTime; // in seconds
uniform vec2 iResolution; // viewport resolution (in pixels) (1080p or 720p)

// all samplers have linear filtering applied, wraping set to repeat
//
uniform sampler1D iFFTTexture; // 1024
uniform float iFFT[8]; // latest frame
uniform float iFFTs[8]; // smoothed latest frame
uniform sampler2D iFFTsHistory; // smoothed fft history, 8x1024, x coord = bin, y coord n-frames earlier, y=0 is latest frame

// predefined textures
//
uniform sampler2D iTex1;
uniform sampler2D iTex2;
uniform sampler2D iTex3;
uniform sampler2D iTex4;
uniform sampler2D iTex5;
uniform sampler2D iTex6;
uniform sampler2D iTex7;
uniform sampler2D iTex8;
uniform sampler2D iNoise;
uniform sampler2D iChecker;

// out_color must be written in order to see anything
//
layout(location = 0) out vec4 out_color;
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////


float dft(vec3 p)
{
	p.z+=iGlobalTime*16.0;
	float d = p.y +8.0 + pow(texture2D(iNoise,p.xz*.001).x,4.0)*50000.0*iFFTs[0] + pow(texture2D(iNoise,p.xz*.0005).x,1.5)*500.0;
	return d *.25;
}


float dfo(vec3 p)
{
	p += sin(p*iFFTs[0]*64.0);
	return (length(p)-1.0)*.15;
}

float df(vec3 p)
{
	return min(dfo(p),dft(p));
}

vec3 nf(vec3 p)
{
	vec2  e = vec2(0.1,.0);
	return normalize(vec3(df(p)-df(p+e.xyy),df(p)-df(p+e.yxy),df(p)-df(p+e.yyx)));
}


vec3 nf2(vec3 p)
{
	vec2  e = vec2(0.001,.0);
	return normalize(vec3(df(p)-df(p+e.xyy),df(p)-df(p+e.yxy),df(p)-df(p+e.yyx)));
}

vec3 bg(vec3 d)
{
	float f = texture( iFFTTexture, (d.x+d.z)*.1-.5  ).r * 20;
	return vec3(.1,.2,.5)*(d.y*.5+.3)+vec3(f);
}

void main(void)
{
	vec2 uv = vec2( gl_FragCoord.xy ) / iResolution;
	vec2 uv5 = uv - 0.5;
	vec2 m;
	m.x = atan(uv5.x / uv5.y);
	m.y = length(uv5);
	float f = texture( iFFTTexture, uv.x  ).r * 10;
float tt = iGlobalTime*.5;
	mat3 rot = mat3(sin(tt),.0,cos(tt),.0,1.0,.0,-cos(tt),.0,sin(tt));

	vec3 pos = vec3(.0,.0,-4.0)+sin(iGlobalTime);
	vec3 dir = vec3(uv5*vec2(1.7,1.0),1.0 - length(uv5));
	dir = normalize(dir);
	float td = .0;

	dir *= rot;
	pos *= rot;
	for (int i = 0; i<200; i++)
	{
		float dd = df(pos); td+=dd;
		pos += dir*dd;
	}
	
		vec3 color = bg(dir);
	
	if (df(pos) < 1.0)
	{
		vec3 n = nf(pos);
		vec3 l = normalize(vec3(sin(iGlobalTime),.6,cos(iGlobalTime)));
		float diffuse = dot(n,l)*.5+.5;
		if (dfo(pos)<dft(pos))
		{
			
			color = vec3(diffuse)*vec3(.4,.2,.2)*.5 + bg(reflect(dir,n));
		}	
		else
		{
			color = vec3(diffuse)*mix(vec3(.1,.2,.1)*2.0,vec3(.9,.3,.1),texture2D(iNoise,pos.zx*.001).x);
		}	


	}

	color = mix(bg(dir),color,1.0/(1.0+td*.005));
	m.y -= iGlobalTime;
	vec4 t = texture( iTex2, m.xy  );
	out_color = vec4(vec3(f)*(1.0+iFFTs[0])+(nf(pos)*.5+.5),1.0);

	color += length(color);
	
	color -= length(uv5)*.5;

	out_color = vec4(color,1.0);
}