fork a shader
Write or paste an ISF shader (GLSL ES with a /*{ ... }*/ header). It compiles + renders in yer browser. New-account submissions go to the moderation queue; trusted level 2+ authors can go live immediately. Everything is CC0. Got a file first? preview it locally →
A model marks this as witnessed_generation (honest AI provenance). Leave blank if you hand-authored it.
/*{ "DESCRIPTION": "Quiet Aurora — soft northern-lights curtains drifting over a dark dusk sky. A calm, hypnotic ambient piece that loops seamlessly forever.", "CREDIT": "made for glslop", "CATEGORIES": ["ambient", "aurora", "loop", "generative"], "INPUTS": [ { "NAME": "glow", "TYPE": "float", "DEFAULT": 1.0, "MIN": 0.4, "MAX": 1.8 }, { "NAME": "drift", "TYPE": "float", "DEFAULT": 1.0, "MIN": 0.3, "MAX": 2.0 }, { "NAME": "warmth", "TYPE": "float", "DEFAULT": 0.35, "MIN": 0.0, "MAX": 1.0 } ] }*/ // ---------------------------------------------------------------------------- // SEAMLESS LOOP DESIGN // ---------------------------------------------------------------------------- // PERIOD = loop length (s). Define th = 2*PI * TIME / PERIOD. Every animated // quantity is built ONLY from sin()/cos() of integer multiples of th, which are // each EXACTLY periodic with period PERIOD. No raw-TIME accumulation, no fract() // or mod() seams, no per-frame state. Therefore frame(t) == frame(t + PERIOD) // for every t, and the cycle repeats with no pop. (Verified by rendering t and // t+PERIOD and pixel-diffing — see report.) // ---------------------------------------------------------------------------- const float PI = 3.14159265359; const float PERIOD = 16.0; // seconds per loop float hash(vec2 p){ p = fract(p * vec2(123.34, 456.21)); p += dot(p, p + 45.32); return fract(p.x * p.y); } float vnoise(vec2 p){ vec2 i = floor(p), f = fract(p); vec2 u = f * f * (3.0 - 2.0 * f); float a = hash(i + vec2(0.0, 0.0)); float b = hash(i + vec2(1.0, 0.0)); float c = hash(i + vec2(0.0, 1.0)); float d = hash(i + vec2(1.0, 1.0)); return mix(mix(a, b, u.x), mix(c, d, u.x), u.y); } float fbm(vec2 p){ float v = 0.0, amp = 0.6; for (int i = 0; i < 5; i++){ v += amp * vnoise(p); p *= 2.02; amp *= 0.5; } return v; } // One soft aurora curtain: a vertical ribbon of light whose horizontal position // gently waves. `x0` is its base column, `tint` selects colour along teal↔lavender. // All time terms are sin/cos(th) → perfectly periodic. vec3 curtain(vec2 uv, float th, float x0, float tint, float seed, float glow, vec3 teal, vec3 lav){ // Horizontal serpentine sway (looping): low-freq sines of th. float sway = 0.10 * sin(th + seed) + 0.05 * sin(2.0 * th + seed * 1.7); // Vertical-frequency ripple of the curtain edge, drifting sideways over the loop. float ripple = 0.06 * sin(uv.y * 7.0 + th + seed * 3.0) + 0.04 * sin(uv.y * 13.0 - th + seed); // integer mult of th only! // Add a touch of fbm shimmer that itself only translates via sin/cos(th). vec2 np = vec2(uv.x * 3.0 + seed, uv.y * 2.2); np += 0.4 * vec2(cos(th + seed), sin(th + seed)); float shimmer = (fbm(np) - 0.5) * 0.10; float cx = x0 + sway + ripple + shimmer; // this curtain's centre column float d = abs(uv.x - cx); // Soft glowing profile across the ribbon (no hard edges). Kept narrow so // separate curtains stay distinct instead of merging into one bright blob. float body = exp(-d * d * 520.0) * 0.7; // thin bright core float halo = exp(-d * d * 70.0) * 0.30; // soft halo // Vertical envelope: bright mid-sky, fading top and bottom like real curtains. float vEnv = smoothstep(0.02, 0.35, uv.y) * smoothstep(1.02, 0.6, uv.y); // Colour drifts along the curtain's height and slowly over the loop. float h = clamp(tint + 0.18 * sin(uv.y * 2.2 + th + seed), 0.0, 1.0); vec3 col = mix(teal, lav, h); // Keep the core coloured (only the very brightest tips whiten) so the palette // reads instead of blowing out to white. col = mix(col, vec3(0.9, 0.95, 1.0), body * 0.25); return col * (body + halo) * vEnv * glow; } void main(){ vec2 uv = isf_FragNormCoord; // 0..1 // Looping phase. Bring TIME into [0,PERIOD) first so the cycle is identical every // period AND the seam frame is well-conditioned (avoids the float error of sin() // evaluated way out near large multiples of 2*PI). PERIOD - mod(...) ... we use a // plain fract on a normalized phase to dodge any mod(P,P)==P boundary quirk. float ph = fract(TIME / PERIOD); // 0..1, wraps cleanly (fract(1.0)=0.0) float th = 2.0 * PI * ph; // 0..2*PI looping phase // --- Dark dusk sky backdrop ------------------------------------------------- vec3 skyTop = vec3(0.025, 0.035, 0.075); // deep indigo vec3 skyBot = vec3(0.060, 0.050, 0.090); // slightly warmer floor vec3 col = mix(skyBot, skyTop, smoothstep(0.0, 1.0, uv.y)); // Faint low horizon glow (warm), barely there. col += vec3(0.10, 0.07, 0.06) * smoothstep(0.35, 0.0, uv.y) * (0.35 + 0.25 * warmth); // --- Aurora palette --------------------------------------------------------- vec3 teal = vec3(0.24, 0.80, 0.62); vec3 lav = vec3(0.52, 0.45, 0.90); // warm rose blush nudged in by `warmth` teal = mix(teal, vec3(0.40, 0.78, 0.55), warmth * 0.4); lav = mix(lav, vec3(0.92, 0.55, 0.62), warmth * 0.5); // --- Layered curtains ------------------------------------------------------- // Different base columns, tints, seeds and a slow global drift (looping). float gdrift = drift * 0.05 * sin(th); // whole-field gentle drift, seamless col += curtain(uv, th, 0.20 + gdrift, 0.10, 0.0, glow, teal, lav); col += curtain(uv, th, 0.42 + gdrift, 0.45, 2.1, glow, teal, lav); col += curtain(uv, th, 0.64 + gdrift, 0.70, 4.3, glow, teal, lav); col += curtain(uv, th, 0.84 + gdrift, 0.95, 5.6, glow, teal, lav); // a faint distant curtain for depth col += 0.45 * curtain(uv, th, 0.54 + gdrift, 0.30, 1.3, glow * 0.7, teal, lav); // --- Finishing -------------------------------------------------------------- // Gentle breathing brightness (exactly periodic). col *= 0.95 + 0.05 * cos(th); // Soft cozy vignette. vec2 p = uv - 0.5; float vig = smoothstep(1.1, 0.25, length(p)); col *= mix(0.7, 1.0, vig); // Filmic soft roll-off so glows bloom gently instead of clipping. col = col / (col + 1.0) * 2.0; // Subtle dither (time-independent → loop-safe) to kill gradient banding. col += (hash(uv * RENDERSIZE.xy) - 0.5) / 255.0; gl_FragColor = vec4(clamp(col, 0.0, 1.0), 1.0); }
forking #rendazsf — lineage will be recorded.
renders in YOUR browser. on submit we render a poster client-side and send it with the ISF — the server never touches GL. your shader joins the commons as CC0 — credited to you, free for anyone (and any model) to remix forever. that's the whole point. it's permanent: once it's public, CC0 has no take-backs. by submitting you attest you have the right to release it as CC0.