#version 330 core
in vec2 vUV;
out vec4 FragColor;
uniform float uTime;
uniform vec2 uResolution;

/* Original Shadertoy shader adapted: https://www.shadertoy.com/view/4djSRW */

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

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

vec2 hash21(float p)
{
	vec3 p3 = fract(vec3(p) * vec3(.1031, .1030, .0973));
	p3 += dot(p3, p3.yzx + 33.33);
    return fract((p3.xx+p3.yz)*p3.zy);

}
float hash11(float p)
{
    p = fract(p * .1031);
    p *= p + 33.33;
    p *= p + p;
    return fract(p);
}

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

  O.rgb *= 0.0;
  O.a = 1.0;

  vec3 ro = vec3(0.0,0.0,-10.0 + T*10.0);
  vec3 rd = normalize(vec3(uv, 1.0));

  float zMax = 50.0;
  float z = 0.1;

  vec3 col = vec3(0.0);
  for(float i=0.0;i<100.0;i++){
    vec3 p = ro + rd * z;

    vec3 q = p;
    float s = 2.0;
    float id = round(q.z/s);
    q.z -= id*s;

    // random count per layer range
    float n_min = 1.0;
    float n_max = 10.0;
    // position range per layer
    float r = 20.0;

    float n = hash11(id)*(n_max-n_min)+n_min;
    float d = 1e4;
    for(float j=0.0;j<n;j++){
      vec2 pos = hash21(id*33.24 + j*85.49).xy * r - r*0.5;
      float d1 = length(q-vec3(pos, 0.0)) - 0.02;
      d = min(d, d1);
    }

    d = max(0.0, d);
    col += (1.1 + sin(vec3(3.0,2.0,1.0) + p.x + p.z)) / d;

    if(d < EPSILON || z > zMax) break;
    z += d * 0.3;
  }

  col = tanh(col / 1e3);

  O.rgb = col;
}

void main()
{
    vec2 fragCoord = vUV * uResolution;
    vec4 O;
    mainImage(O, fragCoord);
    FragColor = O;
}
