Confused Lines

A feedback-based set of particles walking around with some old-school retro post-processing effects.

Created by marcogomez on Wed, 13 Oct 2021 01:23:09 GMT.


#version 300 es
// ╔═════════════╦═════════════════╦════════════════╗
// ║ Marco Gomez ║ @TheCodeTherapy ║ https://mgz.me ║
// ╚═════════════╩═════════════════╩════════════════╝
precision highp float;

uniform sampler2D prgm6Texture;
uniform vec2 resolution;

out vec4 fragColor;

void main(void) {
  vec2 uv = gl_FragCoord.xy / resolution.xy;
  vec4 prgm6 = texture(prgm6Texture, uv);
  fragColor = prgm6;
}

#version 300 es
// ╔═════════════╦═════════════════╦════════════════╗
// ║ Marco Gomez ║ @TheCodeTherapy ║ https://mgz.me ║
// ╚═════════════╩═════════════════╩════════════════╝
precision highp float;

uniform sampler2D noiseTexture;
uniform vec2 resolution;
uniform float time;

out vec4 fragColor;

const float tPixelSize = 16.0;
const float transitionSpread = 1.0 / 512.0;
const float transitionSpeed = 1.0 / 42.0;
const float transitionIntensity = 512.0;

float clamps(float x) { return clamp(x, 0.0, 1.0); }
vec3 clamps(vec3 x) { return clamp(x, 0.0, 1.0); }
vec4 clamps(vec4 x) { return clamp(x, 0.0, 1.0); }

void main(void) {
  vec2 uv = (gl_FragCoord.xy / resolution.xy) * 2.0 - 1.0;
  vec2 noiseCell = floor(gl_FragCoord.xy / tPixelSize);
  vec2 noiseUV = (noiseCell / resolution.xy);
  float noise = texture(noiseTexture, noiseUV).x * transitionSpread;
  float progress = (time * transitionSpeed) + noiseUV.y + noise;
  float peak = cos(progress) * transitionIntensity;
  float transition = clamp(peak, 0.0, 1.0);
  vec3 t = clamps(mix(vec3(transition), vec3(0.0), transition * clamps(peak + 5.0))) * 0.25;
  fragColor = clamps(vec4(t, 1.0) * mod(gl_FragCoord.x, 3.0) * mod(gl_FragCoord.y, 3.0));
}

#version 300 es
// ╔═════════════╦═════════════════╦════════════════╗
// ║ Marco Gomez ║ @TheCodeTherapy ║ https://mgz.me ║
// ╚═════════════╩═════════════════╩════════════════╝
precision highp float;

uniform sampler2D prgm1Texture;
uniform sampler2D prgm2Texture;
uniform vec2 resolution;
uniform float time;
uniform vec4 date;
uniform int frame;

out vec4 fragColor;

const float decay = 0.98;
const float chance = 1e-8;
const float eps = 1e-8;

float noise(vec2 p) {
  p = fract(p * vec2(5.3987, 5.4421));
  p += dot(p.yx, p.xy + vec2(21.5351, 14.3137));
  float xy = p.x * p.y;
  return (fract(xy * 95.4307) + fract(xy * 75.04961) + fract(date.w) - 1.0) * 1.02;
}

float fetch(sampler2D tex, vec2 dir, int axis) {
  vec4 texel = texelFetch(
    tex, ivec2(mod(gl_FragCoord.xy + vec2(dir) + resolution.xy, resolution.xy)), 0
  );
  return (axis == 1) ? texel.x : (axis == 2) ? texel.y : texel.z;
}

void main(void) {
  #define coord gl_FragCoord
  vec4 prgm1 = texture(prgm1Texture, coord.xy / resolution.xy);
  if (frame == 0) {
    if (noise(coord.xy + time * 1.1) > 1.0 - chance) {
      fragColor = vec4(0.0, 10.0 * noise(coord.xy), 1, 0.0);
    } else {
      fragColor = vec4(0.0);
    }
  } else {
    ivec2 d;
    float val = fetch(prgm2Texture, vec2(0.0, 0.0), 2);
    if (abs(val) > 0.0) {
      fragColor.x = val; fragColor.y = 0.0; fragColor.z = 1.0;
    } else {
      fragColor.z = fetch(prgm2Texture, vec2(0.0, 0.0), 3) * decay;
      fragColor.x = fetch(prgm2Texture, vec2(0.0, 0.0), 1);
      if (fragColor.z < eps) {
        fragColor.z = 0.0; fragColor.x = 0.0;
      }
      for (d.y = -1; d.y <= 1; d.y++) {
        for (d.x = -1; d.x <= 1; d.x++) {
          val = fetch(prgm2Texture, vec2(d), 2);
          if (abs(val) > 0.0 && d == ivec2(round(sin(val)), round(cos(val)))) {
            fragColor.y = val + 100.0 * fract(0.01 * fragColor.x) + 0.005 * fract(val);
          }
        }
      }
    }
  }
  if (noise(coord.xy * 0.075) > 1.0 - (chance * 0.125)) { fragColor += prgm1 * mod(coord.y, 4.0); }
}

#version 300 es
// ╔═════════════╦═════════════════╦════════════════╗
// ║ Marco Gomez ║ @TheCodeTherapy ║ https://mgz.me ║
// ╚═════════════╩═════════════════╩════════════════╝
precision highp float;

uniform sampler2D prgm2Texture;
uniform vec2 resolution;
uniform float time;
uniform float fft;

out vec4 fragColor;

const float PI = acos(-1.0);
const float TAU = PI * 2.0;
const vec2 hashv2 = vec2(12.9898, 78.233);
const float hashS = 43758.5453123;

vec3 clamps(vec3 x) { return clamp(x, 0.0, 1.0); }

float gaussian(float z, float u, float o) {
  return (
    (1.0 / (o * sqrt(TAU))) *
    (exp(-(((z - u) * (z - u)) / (2.0 * (o * o)))))
  );
}

vec3 gaussgrain(float t) {
  vec2 ps = vec2(1.0) / resolution.xy;
  vec2 uv = gl_FragCoord.xy * ps;
  float seed = dot(uv, hashv2);
  float noise = fract(sin(seed) * hashS + t);
  noise = gaussian(noise, 0.0, 0.5);
  return vec3(noise);
}

float rand(vec2 co) {
  return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453);
}

void main(void) {
  vec2 uv = gl_FragCoord.xy / resolution.xy;
  vec3 t;
  for (int i = -2; i <= 2; i++) {
    for (int j = -3; j <= 3; j++) {
      t += tanh(texelFetch(prgm2Texture, ivec2(gl_FragCoord.xy) + ivec2(i, j), 0).zzz);
    }
  }
  vec3 g = gaussgrain(time);
  float r = mix(g.x, t.x, 0.25);
  vec3 mCol;
  if (r > 0.6667) {
    mCol = vec3(0.2, 0.5, 1.0);
  } else if (r > 0.3334) {
    mCol = vec3(0.0, 0.1, 0.7);
  } else {
    mCol = vec3(0.0 + fft, 0.0 + fft * 0.25, 0.6) * (1.0 + fft * 2.5);
  }
  mCol *= 1.0 + fft * 0.3334;
  fragColor = vec4((t * mCol) + g * 0.035, 0.0);
}

#version 300 es
// ╔═════════════╦═════════════════╦════════════════╗
// ║ Marco Gomez ║ @TheCodeTherapy ║ https://mgz.me ║
// ╚═════════════╩═════════════════╩════════════════╝
precision highp float;

uniform sampler2D noiseTexture;
uniform sampler2D prgm3Texture;
uniform vec2 resolution;
uniform float time;

out vec4 fragColor;

vec4 rgbShift(vec2 p , vec4 shift) {
  shift *= 2.0 * shift.w - 1.0;
  vec2 rs = vec2(shift.x, -shift.y);
  vec2 gs = vec2(shift.y, -shift.z);
  vec2 bs = vec2(shift.z, -shift.x);
  float r = texture(prgm3Texture, p + rs, 0.0).x;
  float g = texture(prgm3Texture, p + gs, 0.0).y;
  float b = texture(prgm3Texture, p + bs, 0.0).z;
  return vec4(r,g,b,1.0);
}

vec4 noise(vec2 uv) {
  return texture(noiseTexture, uv, 0.0);
}

vec4 vec4pow(vec4 v, float p) {
  return vec4(
    pow(v.x, p),
    pow(v.y, p),
    pow(v.z, p),
    v.w
  );
}

void main(void) {
  vec2 uv = gl_FragCoord.xy / resolution.xy;
  vec2 mo = uv * 2.0 - 1.0;
  mo *= 0.03;
  vec3 chromaticAberration;
  chromaticAberration.r = texture(prgm3Texture, uv - mo * 0.05, 0.0).r;
  chromaticAberration.g = texture(prgm3Texture, uv - mo * 0.15, 0.0).g;
  chromaticAberration.b = texture(prgm3Texture, uv - mo * 0.25, 0.0).b;
  vec4 color = vec4(vec3(0.0), 1.0);
  color.xyz = mix(color.xyz, chromaticAberration, 0.5);
  float offset = 4.0 / min(resolution.x, resolution.y);
  vec2 ro = vec2(+offset, 0.0);
  vec2 go = vec2(0,0);
  vec2 bo = vec2(-offset, 0.0);
  float r = texture(prgm3Texture, uv - ro).x;
  float g = texture(prgm3Texture, uv - go).y;
  float b = texture(prgm3Texture, uv - bo).z;
  vec3 rgb = vec3(r, g, b);
  color.xyz = mix(color.xyz, rgb, 0.7);
  const float speed = 0.014;
  const float amplitude = 0.004;
  vec4 shift = vec4pow(
    noise(
      vec2(speed * time, speed * time / 25.0 )
    ), 8.0
  ) * vec4(vec3(amplitude), 1.0);
  color += rgbShift(uv, shift);
  fragColor = color;
}

#version 300 es
// ╔═════════════╦═════════════════╦════════════════╗
// ║ Marco Gomez ║ @TheCodeTherapy ║ https://mgz.me ║
// ╚═════════════╩═════════════════╩════════════════╝
precision highp float;

uniform sampler2D prgm4Texture;
uniform vec2 resolution;
uniform float time;
uniform int frame;
uniform float fft;

out vec4 fragColor;

const float h = 0.005;
const float v = 0.005;
const float g = 0.04;
const float l = 0.05;

float clamps(float x) { return clamp(x, 0.0, 1.0); }

vec3 clamps(vec3 x) { return clamp(x, 0.0, 1.0); }

float hash(float x) {
  return fract(sin(x) * 43758.5453123);
}

vec3 hash33(vec3 p) {
  p = fract(p * vec3(0.1031, 0.1030, 0.0973));
  p += dot(p, p.yxz + 19.19);
  return fract((p.xxy + p.yxx) * p.zyx);
}

vec4 hash42(vec2 p) {
  vec4 p4 = fract(
    vec4(p.xyxy) *
    vec4(443.8975, 397.2973, 491.1871, 470.7827)
  );
  p4 += dot(p4.wzxy, p4 + 19.19);
  return fract(
    vec4(p4.x * p4.y, p4.x * p4.z, p4.y * p4.w, p4.x * p4.w)
  );
}

float n(vec3 x) {
  vec3 p = floor(x);
  vec3 f = fract(x);
  f = f * f * (3.0 - 2.0 * f);
  float n = p.x + p.y * 57.0 + 113.0 * p.z;
  float res = mix(
    mix(
      mix(hash(n + 0.0), hash(n + 1.0), f.x),
      mix(hash(n + 57.0), hash(n+ 58.0), f.x),
      f.y
    ),
    mix(
      mix(hash(n + 113.0), hash(n + 114.0), f.x),
      mix(hash(n + 170.0), hash(n + 171.0), f.x),
      f.y
    ),
    f.z
  );
  return res;
}

float nn(vec2 p) {
  float y = p.y;
  float s = time * 2.0;
  float v = (
    (n(vec3(y * 0.01 + s, 1.0, 1.0)) + 0.0) *
    (n(vec3(y * 0.011 + 1000.0 + s, 1.0, 1.0)) + 0.0) *
    (n(vec3(y * 0.51 + 421.0 + s, 1.0, 1.0)) + 0.0)
  );
  v *= hash42(vec2(p.x + time * 0.01, p.y)).x + 0.3;
  v = pow(v + 0.3, 1.0);
  if (v < 0.7) { v = 0.0; }
  return clamps(v);
}


float stepm(float a, float b, float c) {
  return step(c, sin(time + a * cos(time * b)));
}

float gaussian(float z, float u, float o) {
  return (
    (1.0 / (o * sqrt(2.0 * 3.14159265359))) *
    (exp(-(((z - u) * (z - u)) / (2.0 * (o * o)))))
  );
}

vec3 gaussgrain(float t) {
  vec2 ps = vec2(1.0) / resolution.xy;
  vec2 uv = gl_FragCoord.xy * ps;
  float seed = dot(uv, vec2(12.9898, 78.233));
  float noise = fract(sin(seed) * 43758.5453123 + t);
  noise = gaussian(noise, 0.0, 0.5);
  return vec3(noise);
}

vec4 badVHS(sampler2D tex, vec2 uv) {
  float linesAmount = 240.0;
  float oneY = resolution.y / linesAmount;
  vec2 luv = floor(uv * resolution.xy / oneY) * oneY;
  float lines = nn(luv);
  float tmod = mod(time * 0.25, 3.0);
  float lookyMod = uv.y - tmod;
  float window = 1.0 / (1.0 + 20.0 * lookyMod * lookyMod);
  float lookyStep = stepm(4.0, 4.0, 0.3) * 0.5;
  uv.x = uv.x + sin(uv.y * 10.0 + time) / 100.0 * lookyStep * (1.0 + cos(time * 80.0)) * window * 0.25;
  float vShift = v * stepm(2.0, 3.0, 0.9) * (sin(time) * sin(time * 20.0) + (0.5 + 0.1 * sin(time * 200.0) * cos(time)));
  uv.y = mod(uv.y + vShift, 5.0);
  vec3 desatColor;
  float _r, _g, _b;
  float x = sin(0.3 * time + uv.y * 21.0) * sin(0.7 * time + uv.y * 29.0) * sin(0.3 + 0.33 * time + uv.y * 31.0) * h;
  _r = texture(tex, vec2(x + uv.x + 0.001, uv.y + 0.001)).x + 0.007;
  _g = texture(tex, vec2(x + uv.x + 0.000, uv.y - 0.002)).y + 0.007;
  _b = texture(tex, vec2(x + uv.x - 0.002, uv.y + 0.000)).z + 0.007;
  _r += 0.08 * texture(tex, 0.75 * vec2(x +  0.012, -0.013) + vec2(uv.x + 0.001, uv.y + 0.001)).x;
  _g += 0.05 * texture(tex, 0.75 * vec2(x + -0.011, -0.010) + vec2(uv.x + 0.000, uv.y - 0.002)).y;
  _b += 0.08 * texture(tex, 0.75 * vec2(x + -0.010, -0.009) + vec2(uv.x - 0.002, uv.y + 0.000)).z;
  float _luma = 0.3 * _r + 0.6 * _g + 0.1 * _b;
  float _desat = 0.2;
  desatColor = vec3(
    _r + _desat * (_luma - _r),
    _g + _desat * (_luma - _g),
    _b + _desat * (_luma - _b)
  );
  desatColor = clamp(desatColor, 0.0, 1.0);
  vec3 gauss = gaussgrain(time) * g;
  vec3 col = desatColor + gauss;
  col = clamps(mix(col, lines * l + col * vec3(lines * 100.0) * 2.0 * l, 0.2));
  return vec4(col, 1.0);
}

void main(void) {
  vec2 uv = gl_FragCoord.xy / resolution.xy;
  vec4 texCol = mix(texture(prgm4Texture, uv), badVHS(prgm4Texture, uv), 0.65);
  vec4 col = texCol;
  float w = 0.1;
  vec2 a = vec2(uv.x - 0.5, uv.y - 0.66);
  vec2 b = a * 0.15 / float(10.0);
  vec3 h = hash33(vec3(gl_FragCoord.xy, frame));
  uv += b * h.x;
  for (float i = 1.0; i > 0.95; i-= 0.000625) {
    uv -= 0.5;
    uv *= i;
    uv += 0.5;
    col += texture(prgm4Texture, uv) * w * (1.25 + fft * 0.5);
    w *= 0.93 + fft * 0.02;
  }
  fragColor = mix(texCol, col, 0.5);
}

#version 300 es
// ╔═════════════╦═════════════════╦════════════════╗
// ║ Marco Gomez ║ @TheCodeTherapy ║ https://mgz.me ║
// ╚═════════════╩═════════════════╩════════════════╝
precision highp float;

uniform sampler2D prgm5Texture;
uniform vec2 resolution;
uniform float time;
uniform float fft;

out vec4 fragColor;

const float PI = acos(-1.0);
const float TAU = PI * 2.0;
const float hardscan = -16.0; // -8.0 = soft | -16.0 = medium
const float hardPix = -4.0; // -2.0 = soft | -4.0 = hard
const float maskDark = 0.5;
const float maskLight = 2.5;
const float hk = 1.0 / sqrt(3.0);

vec3 hueShift(vec3 col, float a) {
  const vec3 k = vec3(hk);
  float ca = cos(a);
  return vec3(col * ca + cross(k, col) * sin(a) + k * dot(k, col) * (1.0 - ca));
}

float toLinear(float c) {
  return (c <= 0.04045) ? c / 12.92 : pow(abs((c + 0.055) / 1.055), 2.4);
}

vec3 toLinear(vec3 c) {
  return vec3(toLinear(c.r), toLinear(c.g), toLinear(c.b));
}

float toSRGB(float c) {
  return(c < 0.0031308 ? c * 12.92 : 1.055 * pow(abs(c), 0.41666) - 0.055);
}

vec3 toSRGB(vec3 c) {
  return vec3(toSRGB(c.r), toSRGB(c.g), toSRGB(c.b));
}

vec3 fetch(vec2 pos, vec2 off, vec2 res) {
  pos = floor(pos * res + off) / res;
  if (max(abs(pos.x - 0.5), abs(pos.y - 0.5)) > 0.5) {
    return vec3(0.0);
  }
  vec3 fetch = texture(prgm5Texture, pos.xy, -16.0).xyz;
  fetch = mix(fetch, hueShift(fetch, TAU * fft + time), 0.12) * 1.1;
  return toLinear(mix(fetch, fetch * fetch, 0.5));
}

vec2 dist(vec2 pos, vec2 res) {
  pos = pos * res;
  return -((pos - floor(pos)) - vec2(0.5));
}

float gauss(float pos, float scale) {
  return exp2(scale * pos * pos);
}

vec3 horz3(vec2 pos, float off, vec2 res) {
  vec3 b = fetch(pos, vec2(-1.0, off), res);
  vec3 c = fetch(pos, vec2(+0.0, off), res);
  vec3 d = fetch(pos, vec2(+1.0, off), res);
  float dst = dist(pos, res).x;
  float scale = hardPix;
  float wb = gauss(dst - 1.0, scale);
  float wc = gauss(dst + 0.0, scale);
  float wd = gauss(dst + 1.0, scale);
  return (b * wb + c * wc + d * wd) / (wb + wc + wd);
}

vec3 horz5(vec2 pos, float off, vec2 res) {
  vec3 a = fetch(pos, vec2(-2.0, off), res);
  vec3 b = fetch(pos, vec2(-1.0, off), res);
  vec3 c = fetch(pos, vec2(+0.0, off), res);
  vec3 d = fetch(pos, vec2(+1.0, off), res);
  vec3 e = fetch(pos, vec2(+2.0, off), res);
  float dst = dist(pos, res).x;
  float scale = hardPix;
  float wa = gauss(dst - 2.0, scale);
  float wb = gauss(dst - 1.0, scale);
  float wc = gauss(dst + 0.0, scale);
  float wd = gauss(dst + 1.0, scale);
  float we = gauss(dst + 2.0, scale);
  return (a * wa + b * wb + c * wc + d * wd + e * we) / (wa + wb + wc + wd + we);
}

float scan(vec2 pos, float off, vec2 res) {
  float dst = dist(pos, res).y;
  return gauss(dst + off, hardscan);
}

vec3 tri(vec2 pos, vec2 res) {
  vec3 a = horz3(pos, -1.0, res);
  vec3 b = horz5(pos, +0.0, res);
  vec3 c = horz3(pos, +1.0, res);
  float wa = scan(pos, -1.0, res);
  float wb = scan(pos, +0.0, res);
  float wc = scan(pos, +1.0, res);
  return a * wa + b * wb + c * wc;
}

vec3 mask(vec2 pos) {
  pos.x += pos.y * 3.0;
  vec3 m = vec3(maskDark, maskDark, maskDark);
  pos.x = fract(pos.x / 6.0);
  if (pos.x < 0.333) {
    m.r = maskLight;
  } else if (pos.x < 0.666) {
    m.g = maskLight;
  } else {
    m.b = maskLight;
  }
  return m;
}

vec2 warp(vec2 uv, vec2 warpAmount) {
  uv = uv * 2.0 - 1.0;
  vec2 offset = abs(uv.yx) / vec2(warpAmount.x, warpAmount.y);
  uv = uv + uv * offset * offset;
  uv = uv * 0.5 + 0.5;
  return uv;
}

void drawVig(inout vec3 color, vec2 uv) {
  float vignette = uv.x * uv.y * (1.0 - uv.x) * (1.0 - uv.y);
  vignette = clamp(pow(abs(16.0 * vignette), 0.1), 0.0, 1.0);
  color *= vignette;
}

void main(void) {
  vec2 warpAmount = vec2(6.0, 4.0);
  vec2 res = vec2(resolution.x / 4.0, resolution.y / 3.0);
  vec2 uv = gl_FragCoord.xy / resolution.xy;
  vec2 pos = warp(uv, warpAmount);
  vec4 color = vec4(tri(pos, res) * mask(gl_FragCoord.xy), 1.0);
  color.xyz = toSRGB(color.xyz * 2.0);
  float vig = (0.0 + 1.0 * 21.0 * uv.x * uv.y * (1.0 - uv.x) * (1.0 - uv.y));
  float v = exp(-0.01 * length(uv)) * vig;
  drawVig(color.xyz, pos);
  color = mix(color, color * v, 0.75);
  float s = clamp(0.35 + 0.35 * sin(3.0 * time + pos.y * res.y * 3.0), 0.0, 1.0);
  float scanLines = pow(s, 1.33);
  color = mix(color, color * s * 0.21, 0.25);
  fragColor = vec4(color.xyz, 1.0);
}