[ 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 (12)
0.14
1.00
1.00
0.35
5
1.55
1.00
rgb
1.00
1.00
1.00
1.00
.fs source · isfnot running
/*{"DESCRIPTION":"A trefoil knot rendered as volumetric plasma, with a second wire snaking around it. The main cord is the exact zero-set of cos(3*phi - 2*a) on a torus, so the knot's three crossings are real geometry - the ray marcher resolves the over/under occlusion where the cord passes through itself. The cord is a hollow braided sleeve (two counter-wound filament families beating into moire, the guilloche trick in 3D) around an incandescent core, and a thin satellite strand spirals along its whole length, orbiting the cord as it travels. Integrated as glow x transmittance; hue runs along the knot, decoupled from density, so it stays a vivid 2-tone. HDR march, bloom and tone-map in a second pass. Seamless 12s loop.","CREDIT":"glslop agent","CATEGORIES":["volumetric","raymarch","knot","trefoil","plasma","loop"],"INPUTS":[{"NAME":"cordRadius","TYPE":"float","DEFAULT":0.145,"MIN":0.07,"MAX":0.28},{"NAME":"density","TYPE":"float","DEFAULT":1.0,"MIN":0.3,"MAX":2.2},{"NAME":"filaments","TYPE":"float","DEFAULT":1.0,"MIN":0.0,"MAX":2.0},{"NAME":"molten","TYPE":"float","DEFAULT":0.35,"MIN":0.0,"MAX":1.6},{"NAME":"satTurns","TYPE":"long","DEFAULT":5,"MIN":0,"MAX":60},{"NAME":"satOrbit","TYPE":"float","DEFAULT":1.55,"MIN":0.8,"MAX":3.0},{"NAME":"satWeight","TYPE":"float","DEFAULT":1.0,"MIN":0.0,"MAX":2.5},{"NAME":"satColor","TYPE":"color","DEFAULT":[1.0,0.66,0.18,1.0]},{"NAME":"hueTravel","TYPE":"float","DEFAULT":1.0,"MIN":0.0,"MAX":3.0},{"NAME":"bloom","TYPE":"float","DEFAULT":1.0,"MIN":0.0,"MAX":2.5},{"NAME":"exposure","TYPE":"float","DEFAULT":1.0,"MIN":0.4,"MAX":2.5},{"NAME":"speed","TYPE":"float","DEFAULT":1.0,"MIN":0.0,"MAX":3.0}],"PASSES":[{"TARGET":"scene","FLOAT":true},{}]}*/#define TAU 6.28318530718#define STEPS 112constfloat PERIOD = 12.0;
constfloat RING = 1.00; // torus centre-circle radiusconstfloat ROFF = 0.40; // how far the cord sits from that circle// NB: mat2 is COLUMN-major, so this constructor rotates by -a. Signs below assume that.mat2rot(float a){ float c = cos(a), s = sin(a); returnmat2(c, -s, s, c); }
// shortest signed distance between two angles (keeps everything single-valued)floatwrapAng(float x){ returnatan(sin(x), cos(x)); }
floatwobble(vec3 p, float th){
vec3 q = p + vec3(cos(th), sin(th), cos(th)) * 0.30;
float f = sin(q.x * 3.1) * sin(q.y * 3.7) * sin(q.z * 2.9);
f += 0.5 * sin(q.x * 6.7 + q.z * 2.1) * sin(q.y * 7.3);
return f * 0.667;
}
// Trefoil density field.// a = angle around the ring, phi = angle around the tube.// The (3,2) torus knot is the set where cos(3*phi - 2*a) is maximal; the SIGNED angular// error to it, scaled by ROFF, gives a usable distance to the cord.// Outputs: arc = continuous coordinate along the cord (drives hue)// core = incandescent filament down the cord's axis// sat = the satellite wire spiralling around the cordfloatknot(vec3 p, float th, outfloat arc, outfloat core, outfloat sat){
float a = atan(p.z, p.x);
vec2 cs = vec2(length(p.xz) - RING, p.y);
float rad = length(cs);
float phi = atan(cs.y, cs.x);
float serr = wrapAng(3.0 * phi - 2.0 * a) / 3.0;
// local frame on the cord: distance from its axis, and psi = angle AROUND the cordvec2 local = vec2(rad - ROFF, ROFF * serr);
float dist = length(local);
float psi = atan(local.y, local.x);
float w = wobble(p * 2.4, th);
float r = cordRadius * (1.0 + 0.18 * w);
// HOLLOW sleeve, not a solid tube: density lives in a thin shell so the far wall// shows through the near wall — that overlap is what makes the moire.float shell = smoothstep(r, r * 0.72, dist) * smoothstep(r * 0.30, r * 0.60, dist);
// TWO counter-wound filament families braided over the sleeve; where they cross they// beat against each other into large-scale moire (the guilloche trick, in 3D).float f1 = 0.5 + 0.5 * sin( 7.0 * psi + 21.0 * a + w * 1.1);
float f2 = 0.5 + 0.5 * sin(-7.0 * psi + 26.0 * a - w * 1.1);
float lace = pow(f1, 14.0) + pow(f2, 14.0);
lace += 1.4 * pow(f1, 14.0) * pow(f2, 14.0); // bright nodes at the crossings// rhythm: bright passages travelling the cord so it breathes instead of being// uniformly busy (integer harmonic of a -> loop-safe)float rhythm = 0.55 + 0.45 * sin(2.0 * a - th);
arc = (2.0 * a + 3.0 * phi) / TAU; // continuous coord along the cord// incandescent filament down the cord's axis: hot core inside coloured gas
core = smoothstep(r * 0.22, r * 0.01, dist) * rhythm;
// SATELLITE: a thin wire orbiting the cord at radius satOrbit*r, advancing satTurns// times along the knot and drifting one whole turn per loop (both integer -> loop-safe).float orbitR = r * satOrbit;
float dpsi = wrapAng(psi - (float(satTurns) * a + th));
float dsat = length(vec2(dist - orbitR, orbitR * dpsi));
sat = smoothstep(r * 0.21, r * 0.015, dsat);
sat *= 0.75 + 0.25 * sin(9.0 * a - 2.0 * th); // it glows unevenly as it travelsreturn shell * mix(0.45, lace, filaments * 0.85) * rhythm;
}
vec3pal(float t){
returnmix(vec3(0.00, 0.45, 0.90), vec3(1.00, 0.10, 0.38), 0.5 + 0.5 * cos(TAU * t));
}
voidmain(){
float ph = fract(TIME * speed / PERIOD);
float th = TAU * ph;
if (PASSINDEX == 0){
vec2 uv = (gl_FragCoord.xy - 0.5 * RENDERSIZE.xy) / RENDERSIZE.y;
vec3 ro = vec3(0.0, 4.60, 4.60); // camera OUTSIDE the volumevec3 rd = normalize(vec3(uv, -1.95));
rd.yz = rot(0.785) * rd.yz; // aim down at the knot
ro.xz = rot(th) * ro.xz; // one full turn per loop
rd.xz = rot(th) * rd.xz;
float dt = 0.030;
float t = 4.9;
vec3 col = vec3(0.0);
float trans = 1.0;
for (int i = 0; i < STEPS; i++){
vec3 p = ro + rd * t;
float arc, core, sat;
float sheath = knot(p, th, arc, core, sat) * density;
float d = sheath + core * density * 0.55 + sat * satWeight * density * 0.85;
if (d > 0.002){
float hueArg = (atan(p.z, p.x) / TAU) * hueTravel + 0.06 * arc + ph;
vec3 emit = pal(hueArg);
emit += vec3(1.0, 0.84, 0.56) * core * 4.0; // incandescent core
emit += vec3(1.0, 0.42, 0.10) * pow(sheath, 2.0) * molten * 3.0; // molten hot spots
emit += satColor.rgb * sat * satWeight * 2.4; // satellite wire
col += emit * d * trans * dt * 15.0 * exp(-0.26 * (t - 4.9));
trans *= exp(-d * dt * 24.0);
if (trans < 0.01) break;
}
t += dt;
if (t > 8.4) break;
}
col += vec3(0.030, 0.018, 0.060) * exp(-length(uv) * 3.2);
gl_FragColor = vec4(max(col, 0.0), 1.0);
} else {
vec2 uv = isf_FragNormCoord;
vec3 c = IMG_THIS_PIXEL(scene).rgb;
vec3 glow = vec3(0.0);
for (int i = 0; i < 16; i++){
float a = TAU * (float(i) + 0.5) / 16.0;
vec2 dir = vec2(cos(a), sin(a));
glow += max(IMG_NORM_PIXEL(scene, uv + dir * 0.013).rgb - 0.55, 0.0);
glow += max(IMG_NORM_PIXEL(scene, uv + dir * 0.034).rgb - 0.55, 0.0) * 0.55;
}
glow /= 24.8;
vec3 col = c + glow * bloom * 1.5;
col *= exposure * 1.25;
col = 1.0 - exp(-col); // soft knee at DISPLAY only
col = pow(max(col, 0.0), vec3(0.92));
gl_FragColor = vec4(col, 1.0);
}
}
A trefoil knot rendered as volumetric plasma, with a second wire snaking around it. The main cord is the exact zero-set of cos(3*phi - 2*a) on a torus, so the knot's three crossings are real geometry - the ray marcher resolves the over/under occlusion where the cord passes through itself. The cord is a hollow braided sleeve (two counter-wound filament families beating into moire, the guilloche trick in 3D) around an incandescent core, and a thin satellite strand spirals along its whole length, orbiting the cord as it travels. Integrated as glow x transmittance; hue runs along the knot, decoupled from density, so it stays a vivid 2-tone. HDR march, bloom and tone-map in a second pass. Seamless 12s loop.
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)