New Retro Lines

A tribute to one of the first programs I've ever wrote in BASIC using the graphical mode of my AppleIIe, back in the early 90s, but with more resolution, colors, and speed though.

Created by marcogomez on Sun, 03 Apr 2022 12:39:16 GMT.


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

uniform sampler2D prgm1Texture;
uniform vec2 resolution;

out vec4 fragColor;

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

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

uniform sampler2D prgm1Texture;
uniform vec2 resolution;
uniform float time;
uniform int frame;

out vec4 fragColor;

const float PI = acos(-1.0);
const float TAU = PI * 2.0;
const float SQRT3 = sqrt(3.0);
const float TAN30 = SQRT3 / 3.0;
const float HALFPI = PI / 2.0;
const float ttp = 1.0 / 3.0;
const float ssp = 2.0 / 3.0;

const float colors = 64.0;
const float repeat = 2.0;
const float offset = 20.0;
const float frate = 60.0;
const float dx0 = 0.8;
const float dx1 = 0.2;

const vec2 d0 = vec2(dx0, sqrt(1.0 - dx0 * dx0)) * offset;
const vec2 d1 = vec2(dx1, sqrt(1.0 - dx1 * dx1)) * offset;

vec3 hueRotate(vec3 c, float a) {
  vec2 zhPI = vec2(0.0, HALFPI);
  vec2 s = sin(vec2(radians(a)) + zhPI);
  vec3 rot = vec3(TAN30, s);
  vec3 cc = cross(rot.xxx, c);
  float dc = dot(rot.xxx, c);
  return mix(rot.xxx * dc, c, rot.z) + cc * rot.y;
}

float line(vec2 p0, vec2 p1, vec2 coord) {
  float proj = clamp(dot(coord - p0, p1 - p0) / dot(p1 - p0, p1 - p0), 0.0, 1.0);
  float dist = length(coord - mix(p0, p1, proj));
  return clamp(1.5 - dist, 0.0, 1.0);
}

vec3 colorize(float t) {
  vec3 color = floor(t / repeat) / colors + vec3(0.0, ttp, ssp);
  return clamp(abs(mod(color, 1.0) * PI - 1.5) - ttp, 0.0, 1.0);
}

vec2 triangle(vec2 delta) {
  return abs(mod(delta, 2.0 * resolution.xy) - resolution.xy);
}

vec3 render(float t, vec2 coord) {
  vec2 p0 = triangle(d0 * t);
  vec2 p1 = triangle(d1 * t);
  return line(p0, p1, coord) * colorize(t);
}

void main(void) {
  vec2 uv = gl_FragCoord.xy / resolution.xy;
  vec4 prgm1 = texture(prgm1Texture, uv);
  float t = floor(time * frate) * 0.5;
  vec3 color = vec3(0.0);
  for (float i = 0.0; i < colors; ++i) {
    color = max(color, render(t + i, gl_FragCoord.xy));
  }
  color = hueRotate(color, time * -TAU * 2.0);
  fragColor = prgm1 * 0.96;
  if (frame % 2 == 0) {
    fragColor += vec4(color, 1.0) * 0.125;
  }
}