Skip to main content
assetsforwordpress

Neon Bars

Neon Bars is a modern WebGL remake of the classic Amiga “copper bars” demo effect. Sine-driven bands of glowing color sweep across the screen, rendered in a single fragment shader with additive glow blending, CRT scanlines, vignette, and film grain.

It respects prefers-reduced-motion: if the visitor has reduced motion enabled in their OS or browser settings, the animation renders a single static frame instead of moving.

Instructions

Remember the good old time

OldSchool Effect

Remember the good old time

OldSchool Effect

This is a basic text element.

This is brilliant

This is a basic text element.

This is colorful

This is a basic text element.

This is magic

This is a basic text element.

This is shining

This is a basic text element.

This is fun

Instructions

Open the JS script in the Supa Code Block element and edit the options at the end of the script. Each option is explained below:

Note on units: the scene renders in "logical pixels" — the canvas is scaled so its height equals 200 logical pixels (scale = H / 200). So values like thick, amp, and glowRadius are in that 200px-tall coordinate space, and they scale proportionally with the canvas size.

Bar geometry & motion

  • bars (default 10) — How many bars to draw. It's rounded and clamped to at least 1 in JS, and the shader hard-caps it at 32 (MAX_BARS). Bars are evenly distributed; the first bar is at the top of the wave stack, the last at the bottom.
  • thick (default 12) — Thickness of each bar in logical pixels. Clamped to a minimum of 0.25 so bars never fully disappear. In the shader, the fragment's distance from the bar's center line is divided by this value to decide if the pixel is inside the bar.
  • amp (default 78) — Amplitude of the sine-wave motion, in logical pixels. This is the maximum vertical travel of a bar before taper/randomness scaling is applied.
  • taper (default 0.75) — Controls how much the amplitude grows from the first bar to the last. Each bar's amplitude is scaled by (1 - taper) + taper × f, where f goes from 0 (first bar) to 1 (last bar). With 0.75, the top bar swings at 25% amplitude and the bottom at 100%, creating the classic "fan-out" copper-bars look. 0 = all bars move identically; 1 = the first bar barely moves.
  • angle (default 0) — Rotation of the whole scene in degrees. The shader rotates the coordinate system around the screen center, so 90 turns the horizontal bars into vertical ones. This also affects scanlines/vignette since they use the rotated position.
  • wav (default 1.6) — Wave frequency: the bars' position is sin(time × wav + …). It's an angular frequency, so higher values mean faster oscillation.
  • phase (default 0.55) — Phase offset between consecutive bars, in radians (+ barIndex × phase). This is what makes the bars move as a traveling wave rather than in unison. 0 = all bars bounce together; larger values create a tighter, more compressed ripple.
  • speed (default 1) — Time multiplier for the animation loop (t += dt × speed). 2 runs twice as fast, 0 freezes the motion, negative values play it in reverse. It's applied in JS, not in the shader.
  • seed (default 0; the boot code uses a random integer) — Randomness seed. seed: 0 gives the deterministic, classic layout (no per-bar jitter). Any non-zero value activates per-bar randomness: each bar gets a pseudo-random phase offset and a "wobble" factor that scales its travel between roughly 35% and 165% of normal. It's deterministic — the same seed always produces the same arrangement.

Color

  • hue (default 190) — Base hue in degrees (0–360) for the first bar. 190 is a cyan/teal. Bars are drawn at full saturation, lightness 0.62.
  • spread (default 26) — Hue shift in degrees added per bar (hue + barIndex × spread). With 10 bars and 26°, you get a smooth cyan→blue→purple→pink gradient across the stack. 0 makes all bars the same color.
  • hueCycle (default 0) — Speed at which the base hue rotates over time (hue + time × hueCycle), in degrees per animation-second. 0 keeps colors static; a small value like 10 creates a slow rainbow drift.
  • alpha (default 1) — Overall opacity of the bars. The bar's brightness profile (a triangle shape across its thickness, strongest at the center) is multiplied by this before blending, so lower values make bars more translucent against the background.
  • blend (default "add") — How bars are combined with what's already drawn. One of "normal", "add", "screen", "multiply", "overlay", "darken", "lighten". "add" is the classic Amiga copper-bars look — overlapping bars sum their colors and blow out toward white where they cross.
  • background (default "#05060d") — Background color as a hex string (#rgb or #rrggbb). Parsed once into RGB floats. Also serves as the reference point for the glow effect (only brightness above the background blooms).

Post-effects

  • glow (default 0.9) — Bloom intensity. When > 0, the shader samples the scene at 8 points around each pixel, averages the light exceeding the background, and adds it back. Higher values give a stronger neon halo around the bars. 0 disables it.
  • glowRadius (default 10) — Radius, in logical pixels, of the circle those 8 glow samples are taken at. Larger = wider, softer halo; smaller = tight glow hugging the bars.
  • noise (default 0) — Amount of animated TV-style grain. Each pixel gets a random offset of (random − 0.5) × noise added to its color, so 0.1 is subtle static and larger values get snowy. 0 disables it.
  • noiseSpeed (default 18) — How fast the grain pattern shifts/refreshes over time. It offsets the noise's sample coordinates by time × noiseSpeed. Only matters when noise > 0.
  • scanlines (default false) — Boolean toggle for CRT scanlines. When true, certain logical pixel rows are darkened.
  • scanGap (default 3) — Scanline period in logical pixels: every Nth row is darkened (row 0, 3, 6, … with gap 3). Minimum forced to 1.
  • scanAlpha (default 0.34) — How strongly the scanline rows are darkened (0–1). The darkened rows are multiplied by 1 − scanAlpha, so 0.34 means those rows render at 66% brightness.
  • vignette (default true) — Boolean toggle for edge darkening. The falloff starts at 30% of the smaller screen dimension from center and reaches full strength at 75% of the larger dimension.
  • vigStrength (default 0.6) — Maximum darkening at the corners/edges (0–1). 0.6 means the far corners can be darkened by up to 60%.

Extra (boot-only)

  • reducedMotion (set to true in the auto-boot call, not in DEFAULTS) — Accessibility switch. When not false, the code checks the browser's prefers-reduced-motion: reduce setting: if the user prefers reduced motion, it renders a single static frame (draw()) instead of starting the animation loop (start()).

Anything you omit falls back to its DEFAULTS value, and you can change options later at runtime via copperBars.set({ ... }) — e.g. set({ hue: 320, bars: 6 }).