Skip to main content
assetsforwordpress

Glowing Metaballs

An interactive WebGL experiment with metaballs: soft, glowing blobs that drift across the canvas, merging and separating as they move. The cursor acts as an attractor — bring the pointer over the canvas and the orbs will gently follow it.
The effect respects the prefers-reduced-motion media query: if reduced motion is enabled in your system settings, the animation is paused and the scene renders as a static frame instead.

Instructions

SEO Expert Adds More Words

The page now ranks slightly better and reads significantly worse.

Mobile Version Almost Considered

It has been added to the roadmap right after “figure out what the roadmap is.

Testimonial Section Testifies to Nothing

“Great service!” says a person whose photo is clearly from a stock library.

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:

count — Number of metaballs

Controls how many metaballs (the liquid blob shapes) are rendered. In the example, it's set to 3. The value is clamped between 1 and maxBalls. Special behavior: if you don't provide this option at all (leaving it null or undefined), the count is randomly generated between 3 and 12 each time you regenerate — that's what the countProvided check does.

size — Ball size multiplier

Scales the radius of every ball. A value of 1.0 is the default; 1.05 in the example makes the blobs slightly larger. Higher numbers mean bigger, fatter blobs; lower numbers make them smaller and more droplet-like.

speed — Animation speed

A time multiplier for the animation. At 1.0 the blobs move at normal speed. Setting it to 2.0 makes everything move twice as fast, 0.5 makes it slow and dreamy, and 0 freezes the motion entirely (which can also disable the animation loop when reduced motion is respected).

threshold — Field merge threshold

Determines how "sticky" the field needs to be before it's rendered as a solid blob. It's the iso-surface cutoff in the shader. Lower values make the balls merge into gooey connected shapes more easily; higher values keep the blobs more separated and distinct. The example uses 0.75, making the balls merge somewhat but remain identifiable.

glow — Glow intensity

Controls how bright and far the halo/glow around the blobs appears. At 0.65 (default) there's a soft luminous aura; higher values create a stronger bloom-like effect, while 0 gives crisp, unlit edges.

noise — Organic distortion

Adds a layer of fractal (fBm) noise to the field, making the blob edges wobbly and organic instead of perfectly smooth. It also subtly perturbs the background. 0.0 (the default and the example value) keeps the shapes clean; small values like 0.2–0.5 give a liquid, lava-lamp feel.

rgbShift — Chromatic aberration

When greater than ~0.005, the shader renders the scene three times (offset for red, green, and blue channels) and combines them, creating a lens/RGB fringing effect. The amount scales with distance from the center, so it's stronger at the edges. The example uses 2.00, which is fairly pronounced; 0 disables it for a cleaner look.

mouse — Mouse interaction

A boolean. When true (default), the blobs are gently attracted toward the cursor position, and there's also a small extra field bump at the pointer. When false, the balls ignore the pointer entirely. The attraction strength is smoothed, so it eases in and out rather than snapping.

hue — Base color hue

Sets the base color of the palette as a hue value from 0 to 1 (on the HSL color wheel: 0 = red, 0.33 = green, 0.58 ≈ blue, 0.675 ≈ blue-purple in the example). If left as null, a random hue is generated each time the scene regenerates. Each ball gets a slight hue jitter on top of this base.

saturation — Color saturation

Clamps the vibrancy of the colors from 0 (grayscale) to 1 (fully saturated). Default is 0.85; the example uses 0.74 for slightly softer colors. Individual balls also get small saturation jitter so they aren't all identical.

scheme — Color distribution scheme

An integer 0–3 that determines how the per-ball hues are spread across the palette:

  • 0 — Analogous: each ball shifts slightly from the base hue (+0.045 per ball), producing a smooth gradient family.
  • 1 — Alternating: balls alternate between the base hue and its complement (base + 0.5), giving a two-tone contrast.
  • 2 — Triadic: hues cycle through three points on the color wheel (0, 0.333, 0.666), producing three distinct color groups.
  • 3 — Monochromatic (used in the example): all balls share the same base hue, varying only slightly via per-ball jitter — a single-hue look.

If left null, one is picked at random on generation.

maxBalls — Shader capacity limit

The maximum number of ball slots compiled into the shader (via #define MAX_BALLS). Default is 16. This is a performance cap: the fragment shader loops over this many balls regardless of count (unused ones get radius 0 and are skipped). Changing it requires shader recompilation, so it should be set at creation time and not changed later.

maxDpr — Maximum device pixel ratio

Caps the resolution multiplier used for the canvas backing store. Default is 2. On high-DPI (Retina) screens, the device pixel ratio could be 3 or more — this option limits rendering resolution to save GPU power. Lower it (e.g., to 1) on weaker devices for better performance at the cost of sharpness.

respectReducedMotion — Accessibility flag

A boolean (default true). When enabled, the animation checks the user's OS/browser preference for "reduced motion" (prefers-reduced-motion: reduce). If the user has requested less motion, the animation loop doesn't run — a single static frame is rendered instead. It also listens for changes to this preference at runtime and starts/stops accordingly. Set to false if you want the animation to always run regardless.

autoGenerate — Randomized initial setup

A boolean (default true). When true (or when a seed is provided), the scene is "generated" at startup: ball positions, sizes, animation frequencies, phases, and color jitters are randomized. If false and no seed is given, only the colors are computed and balls stay at their default (center) positions.

seed — Deterministic randomness

An integer seed for the pseudo-random generator (mulberry32). Providing a seed makes the entire random layout — ball positions, motion patterns, and (if hue/scheme are null) the color choices — fully reproducible: the same seed always produces the exact same scene. The example uses 1115219120 to lock in a specific look. If null, a random seed is chosen each run. You can retrieve the current seed later via getSeed() and replay it with regenerate(seed).

Bonus: ignoreSelector (undocumented in defaults)

Not in the default object, but the code supports opts.ignoreSelector — a CSS selector string for elements that should "block" mouse interaction. If the pointer is over an element matching that selector (e.g., a button or text overlay sitting on top of the canvas), the metaballs ignore the pointer as if it were outside the canvas. Useful for keeping blobs from following the cursor over UI elements.

How they interact

  • count and maxBalls work together: count is how many are visible, maxBalls is the compiled upper limit.
  • hue + saturation + scheme define the palette; seed can override hue/scheme randomly if they're null.
  • threshold + glow + noise shape the visual character of the field.
  • size, speed, and mouse affect motion and scale at runtime (all changeable via setSize, setSpeed, etc. after creation).
  • maxDpr, maxBalls, and respectReducedMotion are primarily performance/accessibility controls.