#version 430 core

uniform float fGlobalTime; // in seconds
uniform vec2 v2Resolution; // viewport resolution (in pixels)

uniform sampler1D texFFT; // towards 0.0 is bass / lower freq, towards 1.0 is higher / treble freq
uniform sampler1D texFFTSmoothed; // this one has longer falloff and less harsh transients
uniform sampler2D texBricks;
uniform sampler2D texGrunge;
uniform sampler2D texMono;
uniform sampler2D texNoise;
uniform sampler2D texNormal;
uniform sampler2D texPaper;
uniform sampler2D texPooBrain;

layout(location = 0) out vec4 out_color; // out_color must be written in order to see anything


float fractal(vec3 p)
{
  float scale=1.;
  for(int i=0; i<7; i++)
  {
    p = -1. + 2*fract(p*.5+.5);
    float k = max( 1.5/dot(p,p), 0.1);
    p *= k;
    scale *= k;
  }
  return 0.25*length(p)/scale;
}

float bt = texture(texFFT, 0.01)*100.;

vec3 sky( vec3 dir)
{
  vec3 col =  mix( vec3(1.,.7,.5), vec3(.5,.7,1.), clamp(max(dir.y,0.)*3.,0.,1.) );
  col += texture(texNoise, dir.xz/dir.y*.002+fGlobalTime*.001).rgb*.1*max(dir.y,0.)*4.;
  col += texture(texNoise, dir.xz/dir.y*.004+bt*.001).rgb*.1*max(dir.y,0.)*2.;
  //col += vec3(1.,.7,.1) * pow( dot(dir,normalize(vec3(0.,1.,-1))), 512.);
  return col;
}

float height( vec2 p)
{
  p*=0.025;
  float h = (texture(texNoise, p*.05+fGlobalTime*.01).r+ texture(texNoise, p*.05-fGlobalTime*.015).b);
  h += (texture(texNoise, p*.1+fGlobalTime*.01).r+ texture(texNoise, p*.1-fGlobalTime*.01).b)*.5;
  h += (texture(texNoise, p*.2+fGlobalTime*.002).r+ texture(texNoise, p*.2-fGlobalTime*.002).b)*.5;
  return h;
}

float map( vec3 p)
{
  return p.y+1. + height(p.xz)*.1 + texture(texFFT, length(p.xz)*0.007).r*8.;
}

vec3 normal( vec3 p)
{
  vec2 eps=vec2(0.01,0.);
  return normalize( vec3( map(p)-map(p+eps.xyy), map(p)-map(p+eps.yxy), map(p)-map(p+eps.yyx)) );
}

void main(void)
{
  vec2 uv = vec2(gl_FragCoord.x / v2Resolution.x, gl_FragCoord.y / v2Resolution.y);
  uv -= 0.5;
  uv /= vec2(v2Resolution.y / v2Resolution.x, 1);
  vec3 org = vec3(0.,0.,-8.);
  vec3 dir = normalize(vec3(uv, 1.-length(uv)*(bt*.1)));
  vec4 p = vec4(org,0.);

 vec3 col = vec3(0.);


  for(int i = 0; i< 64; i++)
  {
    float d = map(p.xyz);
    p += vec4(dir*d, 1./64.);
    if(d<0.01)
      break;
  }
  vec3 n = normal(p.xyz);
  vec3 refdir = reflect( dir, n );

  col += sky(refdir);
  if(dir.y<0.)
  col = mix( vec3(.0,.7,1.), col*vec3(1.,.7,1.), abs(dot(n, refdir))*.5+.5 );
  col = mix(col, sky(dir), 1.-exp(-length(p.xyz-org)*.1) );

  col = pow(col*1.2, vec3(3.2));
  out_color = vec4(col,1.);
}