Skip to main content
assetsforwordpress

Animated Volumetric Side Rays

A soft, cinematic light effect that spills in from the edge of the frame, painted entirely in WebGL with a single fragment shader. The rays drift and pulse on their own, and you can scrub the animation by moving your cursor over the canvas.

Fully customizable, colors, speed, spread, tilt, origin (corners or edge centers), falloff, and more. The effect also respects prefers-reduced-motion: when a visitor has reduced motion enabled in their system settings, it renders a single static frame instead of animating, so the visual stays accessible without losing its look.

Instructions

Another Landing Page in the Void

Statistically, you'll bounce. We've made peace with it.

Our Mission Statement Is Under Revision

Draft 1 was "be a company." Bold. Ambitious. Wrong.

We Sell Things. Buy Them

The transaction means nothing. Do it anyway.

Why Are You Here? (No, Seriously)

We ask ourselves that every morning

Better Than Average, Probably

We ran the numbers. Then we lost the numbers

The #1 Choice for People Who Chose Us

A statistically airtight claim.

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:

canvas — The DOM <canvas> element the effect renders into. The function grabs a WebGL context on it, sizes it to match its CSS box (device-pixel-ratio aware, capped at 2×), and draws the shader output there.

options — An optional object merged over the defaults, so you can pass any subset of the values below. Anything omitted uses its default, unknown keys are ignored, and passing nothing at all is fine.

Geometry & Placement

origin (default: 'top-right') — Where the rays emanate from. Valid values: 'top-right', 'top-left', 'bottom-right', 'bottom-left', 'top', 'bottom', 'left', 'right'. Each value internally maps to a horizontal/vertical flip of the coordinates, a position offset for the light source, and the direction the rays point. Invalid strings silently fall back to 'top-right'. This is the biggest "recompose the whole effect" knob.

tilt (default: 0) — Rotation of the entire ray fan, in degrees, around the origin point. 0 means as-designed per origin; positive values rotate the fan, useful for aligning rays with a diagonal design element.

spread (default: 2) — The angular separation between the two colored ray layers. Internally computed as spread * 0.275: layer 1 points along baseAngle + halfSpread, layer 2 along baseAngle − halfSpread. Higher values fan the two colors apart into a wider fan; lower values make them overlap tightly.

Color

rayColor1 (default: '#EAB308', a yellow) — Hex color of the first ray layer. Converted to normalized RGB internally. Must be a 6-digit hex string — the parser only accepts #rrggbb (no 3-digit shorthand, no rgb()). An invalid value silently falls back to white.

rayColor2 (default: '#96c8ff', a light blue) — Hex color of the second ray layer, same constraints as above. This layer always animates at 20% of speed internally, so it drifts slowly against layer 1, creating a layered shimmer.

blend (default: 0.75) — Mix ratio between the two layers. 0 shows only rayColor1, 1 shows only rayColor2, 0.5 is an equal mix. The default 0.75 favors the second color.

saturation (default: 1.5) — Saturation adjustment applied after lighting: the shader mixes each pixel toward its grayscale luminance. 0 = grayscale, 1 = true colors, > 1 = oversaturated/punchy (the default intentionally pushes colors hotter). Negative values invert toward negative-image colors.

opacity (default: 1) — Final transparency of the whole effect, derived from max(r, g, b) * opacity. Since the context uses premultiplied alpha, this controls how strongly the rays composite over whatever sits behind the canvas. 0 = invisible; useful for subtle background washes at 0.3–0.6.

Light & Brightness

intensity (default: 2) — Overall brightness multiplier feeding brightness = intensity * 0.4 / pow(distance, falloff). Higher values make the rays hotter and brighter near the source; pushed too far (e.g. 4+) they blow out to white.

falloff (default: 1.6) — How fast brightness decays with distance from the ray source — it's the exponent in that pow(). Higher values (e.g. 2.5) concentrate the effect near the origin corner; lower values (e.g. 1.0–1.3) let rays reach much farther across the canvas. The usage example's 1.35 stretches them noticeably beyond the default.

Motion

speed (default: 2.5) — Animation speed of the ray shimmer, feeding the time term in the shader's sine/cosine wave functions. Higher = rays pulse and flicker faster. Note the second color layer always runs at 20% of this, so raising it also widens the speed contrast between layers.

mouseInfluence (default: 1.5) — Pointer "scrubbing" of the animation phase. The cursor position is normalized to -1..1 inside the canvas, averaged, multiplied by this value, and added to the shader's time — so moving the mouse shifts the ray pattern forward/backward in its animation. 0 disables mouse interaction entirely. Movement is exponentially smoothed for a fluid lag effect, and only responds while the cursor is inside the canvas — outside, it holds its last value while the ambient animation keeps running.

Behavior / Performance / Accessibility

respectReducedMotion (default: true) — Accessibility switch. When true and the user has "prefers-reduced-motion: reduce" enabled in their OS/browser, the continuous animation loop is suspended and only a static frame is drawn. It also reacts live — if the user flips the preference mid-session, the effect updates immediately. Set false to ignore the OS preference (generally discouraged).

pauseOffscreen (default: true) — Performance switch. When true, an IntersectionObserver pauses the render loop whenever the canvas scrolls out of the viewport and resumes when visible again. The animation is always paused when the browser tab is hidden, regardless of this flag. Set false to keep animating offscreen (wastes GPU and battery).

Bonus — the returned API

The function returns a control object with setOptions() (live-update any option), getOptions(), pause() / resume() / isPaused(), isReducedMotion(), and destroy() (removes all listeners and releases the WebGL context).

As a quick mental model, grouped in plain words:

  • Where and what shape: origin, tilt, spread
  • What color: rayColor1, rayColor2, blend, saturation, opacity
  • How bright and how far it reaches: intensity, falloff
  • How it moves: speed, mouseInfluence
  • When it runs: respectReducedMotion, pauseOffscreen