#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; // generic textures
uniform sampler2D iTex2;
uniform sampler2D iTex3;
uniform sampler2D iTex4;
uniform sampler2D iTex5;
uniform sampler2D iTex6; // noise
uniform sampler2D iTex7; // moqui
uniform sampler2D iTex8; // okkie
uniform sampler2D iNoise; // perlin noise
uniform sampler2D iChecker; // checker pattern

// out_color must be written in order to see anything
//
layout(location = 0) out vec4 out_color;
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

float df(vec3 p)
{
	p = mod(p+4.0,8.0)-4.0;
	p += sin(p*(4.0+iFFT[5]*1.0)) + sin(p*16*4.0)*.0;
	return (length(p)-5.0 + iFFT[0] + sin(iFFT[1])*.5)*.2 ;
}

vec3 nf(vec3 p)
{
	vec2 e= vec2(.001,.0);
	vec3 n = normalize(vec3(df(p)-df(p+e.xyy),df(p)-df(p+e.yxy),df(p)-df(p+e.yyx)));
	return normalize(n+sin(p*100.0)*.2);
}


void main(void)
{
	float amp = iFFT[0];
	vec2 uv = vec2( gl_FragCoord.xy ) / iResolution * vec2(1,-1);
	float f = texture( iFFTTexture, pow(uv.x*.8*(amp+.2)+.2,4.0)  ).r * 1;
	f -= uv.y+.5;
	f = 0.05/(.05+abs(f));
	//vec4 t = texture( iTex7, uv.xy*(1.0+amp)  )*amp*.5;


	vec3 bgcol = vec3(iFFT[0],iFFT[2],iFFT[6]);
	bgcol = normalize(bgcol);

	float t = iGlobalTime;
	mat3 rot = mat3( sin(t), .0, cos(t),
	.0,1.,.0,-cos(t),.0,sin(t));

	vec3 pos = vec3(2.0 +sin(iGlobalTime),2.0 +sin(iGlobalTime*4.0),-4.0);
	vec2 uv2 = uv -vec2 (.5,-.5);
	vec3 dir = vec3(uv2,1.0 - length(uv2*vec2(.6,.9))*2.0);
	dir.x*=1.5;
	dir = normalize(dir);

	pos *= rot;
	dir *= rot;

	pos.z+=iGlobalTime*2.0+iFFT[0]*4.0;

	float td = .0;

	for (int i=0 ;i<200; i++)
	{
		float dd = df(pos);
		pos += dir*dd;
		td += dd;

	}
	
	
	
	vec3 color = f*bgcol*.3 + dot(nf(pos),normalize(vec3(sin(iGlobalTime),sin(iGlobalTime*3.2),.2)))*.2*bgcol.zyx+.2 + pow(1.0-dot(dir,nf(pos)),4.0)*.5;
	color = min(vec3(1.0),color);
	color = mix(f*bgcol,color,1.0/(1.0+td*.001));
	
	color += length(color);
	color -= length(uv)*.56;
	out_color = vec4(color,1.);
}











