// License CC0: "Rasterbars" in 2022
//  Was tinkering with recreating the classic raster bar effect from 1980/1990
//  Having a _bit_ more compute power I need to put a twist on it obviously


#define PI          3.141592654
#define ROT(a)      mat2(cos(a), sin(a), -sin(a), cos(a))


// ---==> Some parameters to play around with <==---
// Undefine to use old specular lighting
#define COLORBURN
#define SKYDOME
const int   bars     = 7;
const mat2  trans    = ROT(PI/9.0);
const float twist    = 1.0;
const float dist     = 0.5;
const float rounding = 0.125;

#define TAU         (2.0*PI)
#define RESOLUTION  iResolution
#define TIME        iTime

#define MAX_RAY_LENGTH  15.0
#define MAX_RAY_MARCHES 70
#define TOLERANCE       0.00001
#define NORM_OFF        0.005

int g_hit = 0;

// License: WTFPL, author: sam hocevar, found: https://stackoverflow.com/a/17897228/418488
const vec4 hsv2rgb_K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 hsv2rgb(vec3 c) {
  vec3 p = abs(fract(c.xxx + hsv2rgb_K.xyz) * 6.0 - hsv2rgb_K.www);
  return c.z * mix(hsv2rgb_K.xxx, clamp(p - hsv2rgb_K.xxx, 0.0, 1.0), c.y);
}
// License: WTFPL, author: sam hocevar, found: https://stackoverflow.com/a/17897228/418488
//  Macro version of above to enable compile-time constants
#define HSV2RGB(c)  (c.z * mix(hsv2rgb_K.xxx, clamp(abs(fract(c.xxx + hsv2rgb_K.xyz) * 6.0 - hsv2rgb_K.www) - hsv2rgb_K.xxx, 0.0, 1.0), c.y))

// License: Unknown, author: Unknown, found: don't remember
float hash(float co) {
  return fract(sin(co*12.9898) * 13758.5453);
}

// License: MIT OR CC-BY-NC-4.0, author: mercury, found: https://mercury.sexy/hg_sdf/
float mod1(inout float p, float size) {
  float halfsize = size*0.5;
  float c = floor((p + halfsize)/size);
  p = mod(p + halfsize, size) - halfsize;
  return c;
}

vec3 band_color(float ny) {
  vec3 hsv = vec3(0.0);
  float ramp = 1.0/abs(ny);
  if (abs(ny) < 4.0) {
    hsv = vec3(0.0, 0.0, 0.);
  } else if (ny > 0.0) {
    hsv = vec3(0.88, 2.5*ramp,0.8);
  } else {
    hsv = vec3(0.53, 4.0*ramp, 0.8);
  }

  return hsv2rgb(hsv);
}

// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm
float box(vec2 p, vec2 b, vec4 r) {
  r.xy = (p.x>0.0)?r.xy : r.zw;
  r.x  = (p.y>0.0)?r.x  : r.y;
  vec2 q = abs(p)-b+r.x;
  return min(max(q.x,q.y),0.0) + length(max(q,0.0)) - r.x;
}

float df_bars(vec3 p) {
  p.xy *= trans;
  float tm = TIME;
  p.y += dist*sin(0.5*p.x+0.5*p.z+tm);
  vec2 bp = p.zy;

  float d = 1E6;

//  float bs = 0.25*smoothstep(-0.9, -0.25, -cos(0.1*p.x+tm));
  const float bs = 0.25;
  vec2 bsz = vec2(bs);
  vec4 brd = vec4(bs*rounding);

  for (int i = 0; i < bars; ++i) {
    float ii = float(i);
    vec2 pp = bp;
    float a = -tm+0.5*ii;
    float b = ii+p.x-2.0*tm;
    pp.y += sin(a);
    mat2 rot =  ROT(-PI/4.0*cos(a+twist*b));
    pp.x -= bsz.x*sqrt(2.0)*ii;
    pp *= rot;
    float dd = box(pp, bsz, brd);
    if (dd < d) {
      g_hit = i;
      d = dd;
    }
  }

  return d;
}

float df(vec3 p) {
  return df_bars(p);
}

float rayMarch(vec3 ro, vec3 rd, float ti, out int iter) {
  float t = ti;
  int i = 0;
  for (i = 0; i < MAX_RAY_MARCHES; i++) {
    float d = df(ro + rd*t);
    if (d < TOLERANCE || t > MAX_RAY_LENGTH) break;
    t += d;
  }
  iter = i;
  return t;
}

vec3 normal(vec3 pos) {
  vec2  eps = vec2(NORM_OFF,0.0);
  vec3 nor;
  nor.x = df(pos+eps.xyy) - df(pos-eps.xyy);
  nor.y = df(pos+eps.yxy) - df(pos-eps.yxy);
  nor.z = df(pos+eps.yyx) - df(pos-eps.yyx);
  return normalize(nor);
}

const vec3 lightPos = vec3(2.0, 3.0, -5.0);
const vec3 lightCol = vec3(HSV2RGB(vec3(0.53, 0.5, 1.0)));
const vec3 overCol  = vec3(HSV2RGB(vec3(0.88, 0.25, 0.8)));

vec3 skyColor(vec3 ro, vec3 rd) {
  vec3  ld    = normalize(lightPos - ro);
  float dif   = max(dot(ld, rd), 0.0);

  vec3  col   = vec3(0.0);

  if ((rd.y > abs(rd.x)*1.0) && (rd.y > abs(rd.z*0.25))) {
    col = 2.0*overCol*rd.y;
  }
  float rb = length(max(abs(rd.xz/max(0.0,rd.y))-vec2(0.9, 4.0),0.0))-0.1;

  col += overCol*pow(clamp(1.0 - rb*0.5, 0.0, 1.0), 6.0);
  col += lightCol*pow(dif, 8.0);
  col += 4.0*lightCol*pow(dif, 40.0);
  return col;
}

vec3 effect(vec2 p) {
  vec3 ro = vec3(0.0, 0.0, -5.0);
  vec3 la = vec3(0.0, 0.0, 0.0);
  vec3 ww = normalize(la-ro);
  vec3 uu = normalize(cross(vec3(0.0,1.0,0.0), ww ));
  vec3 vv = normalize(cross(ww,uu));
  const float fov = 3.0;
  vec3 rd = normalize(-p.x*uu + p.y*vv + fov*ww );

  int iter;
  g_hit = -1;
  float t = rayMarch(ro, rd, 4.0, iter);
  int hit = g_hit;

  vec3 col = vec3(1.0);
  vec3 bcol = band_color(-4.0*float(hit-(bars-1)/2));
  bcol *= bcol;
  if (t < MAX_RAY_LENGTH) {
    vec3 p = ro + rd*t;
    vec3 n = normal(p);
    vec3 r = reflect(rd, n);
    vec3 ld= normalize(lightPos-p);

    float dif = max(dot(ld, n), 0.0);
    col = bcol*mix(0.5, 1.0, dif);
#ifdef SKYDOME
    vec3 rs= skyColor(p, r);
    float fre = 1.0+dot(rd, n);
    fre *= fre;
    float rf  = mix(0.05, 1.0, fre);
    col += rf*rs;
#else
    float spe = pow(max(dot(ld, r), 0.0), 30.0);
    col += spe;
#endif
  }

  return col;
}


void mainImage(out vec4 fragColor, in vec2 fragCoord) {
  vec2 q = fragCoord/iResolution.xy;
  vec2 p  = -1. + 2. * q;
  p.x     *= RESOLUTION.x/RESOLUTION.y;

  vec3 col  = effect(p);
#if defined(COLORBURN)
  col -= vec3(0.2, 0.3, 0.2);
#endif
  col += smoothstep(4.0, 0.0, TIME);
  col = clamp(col, 0.0, 1.0);
  col = sqrt(col);
  fragColor = vec4(col, 1.0);
}
