#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 fbm(vec2 uv)
{
  uv = uv * 0.00002 + vec2(0.0, fGlobalTime * 0.01);
  return texture2D(texNoise, uv) + texture2D(texNoise, uv * 16.0) * 0.2 * (1.0 - texture(texFFT, 0.01).r);
}

float map(vec3 pos)
{
  float a = pos.z * 0.004 * sin(fGlobalTime * 0.1);
  mat2 m = mat2(cos(a), sin(a), -sin(a), cos(a));
  pos.xy = m * pos.xy;
  return pos.y + fbm(pos.xz) * 100.0;
}

vec3 mtl(vec3 pos)
{
  return pow(texture2D(texPaper, pos.xz * 0.01 + vec2(0.0, fGlobalTime * 0.01)).xyz, vec3(0.5)).xxx * vec3(0.5, exp(-fract(fGlobalTime * 4.0)), 0.9);
}

vec3 n(vec3 pos)
{
  vec2 e = vec2(0.01, 0.0);
  return normalize(vec3(map(pos + e.xyy), map(pos + e.yxy), map(pos + e.yyx)) - vec3(map(pos)));
}

void main(void)
{
  vec2 uv = (gl_FragCoord.xy - v2Resolution * 0.5) / v2Resolution.y;
  uv *= 1.0 - texture(texFFT, 0.01).r * 0.8;

  uv.x += cos(uv.y * 800.0) * texture(texFFT, 0.04) * 0.3;
  vec3 dir = normalize(vec3(uv, 1.0));
  dir.x += cos(fGlobalTime) * 0.4;
  
  float a = fGlobalTime;
  mat2 m = mat2(cos(a), sin(a), -sin(a), cos(a));
  dir.xy = m * dir.xy;
  dir = normalize(dir);

  vec3 pos = vec3(0.0, 10.0 + texture(texFFT, 0.01).r * 50.0, 0.0);
  for (int i = 0; i < 64; i++)
  {
    float d = map(pos);
    pos += dir * d;
  }
  
  vec3 light = normalize(vec3(0.5, 0.1, 1.0));
  
  vec3 diff = (dot(n(pos), light) * 0.5 + 0.5) * mtl(pos);
  float fog = exp(-pos.z * 0.001);
  float atm = max(pow(dot(dir, light), 8.0), 0.0);
  vec3 sky = mix(vec3(0.7, 0.9, 1.0), vec3(1.0, 0.9, 0.6), atm) * 1.2;
  vec3 color = mix(sky, diff, fog);
  
  color = color * smoothstep(1.2, 0.4 - texture(texFFT, 0.01).r, length(uv));
  
  out_color = vec4(color, 1.0);
}
