glsl-fragment-backgrounds

Installation
SKILL.md

GLSL Fragment Shader Backgrounds

When to use this

  • You want an animated, organic-feeling full-screen background (gradient blobs, plasma, flowing noise fields) that would be expensive or impossible to achieve with CSS gradients/animations alone.
  • You need a background that reacts continuously to time and optionally mouse position, rendered at native resolution with GPU-parallel cost instead of CPU-bound canvas 2D drawing.
  • You are comfortable setting up a minimal WebGL/Three.js/regl harness to run a single full-screen triangle with a fragment shader, or already have one via three-js-fundamentals.
  • Do NOT use this for a full 3D scene with real geometry, lighting, and camera movement; that's three-js-fundamentals/react-three-fiber-drei. Do NOT use this if a CSS gradient with background-position animation or an SVG filter achieves the same visual at a fraction of the complexity; reach for a shader specifically when the effect needs continuous procedural noise/domain-warping that CSS cannot express.

Mental model

A full-screen fragment shader background is conceptually the simplest possible use of the GPU's rasterization pipeline: you draw one triangle (or a plain quad) that exactly covers the viewport, and every visible pixel gets computed independently and in parallel by your fragment shader, with zero real geometry to speak of. The vertex shader's only job is a "passthrough": take a hardcoded set of clip-space positions for a full-screen triangle, output them unchanged, and pass UV coordinates to the fragment shader for interpolation.

UV space is the coordinate system your fragment shader actually works in: vUv typically ranges from (0,0) at one corner to (1,1) at the opposite corner, but you almost always want to correct for aspect ratio before using UV coordinates for anything shape-based (circles, noise scale), or your effect will look stretched on non-square viewports. The standard fix is vec2 uv = (gl_FragCoord.xy - 0.5 * resolution.xy) / resolution.y; which centers the coordinate system at the middle of the screen and normalizes by height, so a distance of 1.0 in uv space means the same physical distance in both x and y regardless of aspect ratio.

The time uniform (seconds elapsed, updated from JS every frame) is what turns a static procedural pattern into an animated one: almost every interesting effect is "take a noise function, offset one of its inputs by time * speed." Simplex noise (or its close relative, Perlin noise) is the actual procedural randomness source; raw random() (hash-based pseudo-randomness) produces uncorrelated static, while simplex noise produces smoothly-varying continuous randomness, which is what "organic" motion actually requires. Fractal Brownian Motion (fBm) layers multiple octaves of simplex noise at increasing frequency and decreasing amplitude to produce more natural, detailed-but-coherent texture, the same technique used for procedural terrain and clouds.

Domain warping is the technique that elevates flat noise into the flowing, marbled, plasma-like look associated with premium generative backgrounds: instead of sampling noise directly at a UV coordinate, you first sample noise to get an offset vector, add that offset to your UV coordinates, and then sample noise again at the warped position. This can be nested multiple times (warp the warp) for increasingly complex, non-repeating flow patterns, and is the single biggest lever for making a noise field look intentional rather than like generic Perlin static.

Installs
2
First Seen
Aug 30, 2026
glsl-fragment-backgrounds — avnehsbhatia/ultraui