#version 330 core

#define T iTime
#define PI 3.141596
#define S smoothstep
const float EPSILON = 1e-6;

uniform vec3 iResolution;
uniform float iTime;
uniform float uAlpha;

out vec4 FragColor;

mat2 rotate(float a){
  float s = sin(a);
  float c = cos(a);
  return mat2(c,-s,s,c);
}

float sdRoundBox( vec3 p, vec3 b, float r )
{
  vec3 q = abs(p) - b + r;
  return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0) - r;
}

float fbm(vec3 p){
  float amp = 1.;
  float fre = 1.;
  float n = 0.;
  for(float i =0.;i<4.;i++){
    n += abs(dot(cos(p), vec3(.1)));
    amp *= .5;
    fre *= 2.;
  }
  return n;
}

float hash12(vec2 p)
{
	vec3 p3  = fract(vec3(p.xyx) * .1031);
    p3 += dot(p3, p3.yzx + 33.33);
    return fract((p3.x + p3.y) * p3.z);
}

float hash11(float v){
    return abs(cos(v*2.+sin(v*4.)/4.)/2.);
}

void mainImage(out vec4 O, in vec2 I){
  vec2 R = iResolution.xy;
  vec2 uv = (I*2.-R)/R.y;

  O.rgb *= 0.;
  O.a = 1.;

  vec3 ro = vec3(0.);

  vec3 rd = normalize(vec3(uv, 1.));

  float zMax = 50.;
  float z = .1;

  vec3 col = vec3(0);
  vec3 p;
  for(float i=0.;i<100.;i++){
    p = ro + rd * z;
    p.z += iTime*12.;
    p.xy *= rotate(p.z*.1);
    p.y = -abs(p.y)+10.;
    
    float d0 = abs(p.y)*.1;
    d0 = abs(d0)+.1;

    vec3 q = p;
    float s = 2.;
    vec2 id = round(q.xz/s);
    q.xz -= id*s;
    float d1 = sdRoundBox(q, vec3(.8, .2, .8), .1);
    d1 = max(0.01, d1*.6);
    float d = min(d0, d1);

    d = d * (1.-hash12(uv.xy*30.+iTime)*.1);

    float n = hash12(id+T*3e-4);
    float glow = n >.5 ? (n*2.) : 0.;

    col += glow*(.5+.5*sin(vec3(3,2,1)+id.x+id.y))/d0;

    if(d<EPSILON || z>zMax) break;
    z += d;
  }
  col = tanh(col / 2e2);

  O.rgb = col;
}

void main()
{
    vec4 o;
    mainImage(o, gl_FragCoord.xy);
    o.a *= uAlpha;
    FragColor = o;
}
