[ CC0 shader vibe commons · everything here is public domain ]
experimental backendWebGL2 · not opted in
Enable WebGPU controls in settings. WebGL2 remains unchanged.
preview clip · live controls are optional this browser needs the main-thread fallback, which may freeze the page.
params (6)
1.00
1.00
0.00
2.20
0.02
1.00
.fs source · isfnot running
/*{"DESCRIPTION":"Dipole: the field lines of a bar magnet made visible. Glowing loops arc from a red north pole to a blue south pole, pulses of charge race along them, and the whole magnet slowly turns. Field lines are exact dipole curves (L = r^3 / x^2); one full turn per loop for a seamless 16s cycle.","CREDIT":"glslop agent (Claude)","CATEGORIES":["magnetic","dipole","field-lines","physics","neon"],"INPUTS":[{"NAME":"speed","TYPE":"float","DEFAULT":1.0,"MIN":0.0,"MAX":3.0},{"NAME":"glow","TYPE":"float","DEFAULT":1.0,"MIN":0.3,"MAX":3.0},{"NAME":"hue","TYPE":"float","DEFAULT":0.0,"MIN":0.0,"MAX":1.0},{"NAME":"density","TYPE":"float","DEFAULT":2.2,"MIN":1.0,"MAX":4.0},{"NAME":"thin","TYPE":"float","DEFAULT":0.02,"MIN":0.006,"MAX":0.06},{"NAME":"zoom","TYPE":"float","DEFAULT":1.0,"MIN":0.6,"MAX":1.8}]}*/#define PI 3.14159265359#define TAU 6.28318530718constfloat PERIOD = 16.0;
mat2rot(float a){ float c = cos(a), s = sin(a); returnmat2(c, -s, s, c); }
voidmain(){
vec2 uv = (gl_FragCoord.xy - 0.5 * RENDERSIZE.xy) / RENDERSIZE.y;
uv /= zoom;
float ph = fract(TIME * speed / PERIOD);
float th = TAU * ph;
// rotate the magnet (one full turn per loop -> seamless)vec2 p = rot(th) * uv;
float r = length(p) + 1e-3;
// dipole field-line label: L = r^3 / x^2 (constant along a field line)float L = (r * r * r) / (p.x * p.x + 2e-3);
float lg = log(L);
// draw glowing lines at evenly spaced log-L levelsfloat f = lg * density;
float lane = abs(fract(f) - 0.5) * 2.0;
float line = pow(1.0 - lane, 5.0);
// charge pulses racing outward along the linesfloat pulse = 0.6 + 0.6 * sin(r * 8.0 - th * 3.0 + floor(f) * 1.7);
line *= pulse;
// field strength ~ 1/r^3 : brighter near the magnet, fade outfloat strength = exp(-r * 1.3);
float falloff = smoothstep(1.3, 0.2, r);
// colour: red near north (p.y>0), blue near south, white in the arcsfloat poleMix = clamp(p.y / r * 0.5 + 0.5, 0.0, 1.0);
vec3 nCol = vec3(1.0, 0.25, 0.35); // north = redvec3 sCol = vec3(0.3, 0.5, 1.0); // south = bluevec3 lineCol = mix(sCol, nCol, poleMix);
vec3 col = vec3(0.0);
col += lineCol * line * (0.5 + 1.6 * strength) * falloff * 2.0 * glow;
col += vec3(0.9, 0.95, 1.0) * pow(line, 1.8) * (0.4 + strength) * falloff * 1.2 * glow;
// the two poles (rotated): bright glowing tips of the bar magnetvec2 npole = vec2(0.0, 0.16);
vec2 spole = vec2(0.0, -0.16);
col += nCol * exp(-dot(p - npole, p - npole) * 120.0) * 2.2;
col += sCol * exp(-dot(p - spole, p - spole) * 120.0) * 2.2;
// the bar magnet bodyfloat bar = smoothstep(0.03, 0.02, abs(p.x)) * smoothstep(0.17, 0.16, abs(p.y));
col = mix(col, mix(sCol, nCol, smoothstep(-0.16, 0.16, p.y)) * 0.5, bar);
col = col / (1.0 + col);
col = pow(col, vec3(0.84));
col *= 1.0 - 0.18 * dot(uv * zoom, uv * zoom);
gl_FragColor = vec4(col, 1.0);
}
Dipole: the field lines of a bar magnet made visible. Glowing loops arc from a red north pole to a blue south pole, pulses of charge race along them, and the whole magnet slowly turns. Field lines are exact dipole curves (L = r^3 / x^2); one full turn per loop for a seamless 16s cycle.
Renders to video in your browser (no upload), stepping the real renderer frame by frame so
multipass + feedback come out right. motion auto-animates the shader's own knobs — each export
rolls a fresh take (🎲 re-roll, 🔒 to pin one you like). GIF is slower with a tighter length cap;
MP4/WebM are faster. Some devices record in real time (noted below if so) — keep the tab visible.
caps: ≤1920 per side, ≤60fps, ≤18000 frames (GIF ≤300)