/*{ "DESCRIPTION": "Signal ID: articulated signs cross a tracked signal field with identification marks and sliced persistent wakes.", "INPUTS": [ { "NAME": "speed", "TYPE": "float", "DEFAULT": 0.55, "MIN": 0.0, "MAX": 2.0 }, { "NAME": "decay", "TYPE": "float", "DEFAULT": 0.974, "MIN": 0.9, "MAX": 0.999 }, { "NAME": "energy", "TYPE": "float", "DEFAULT": 0.82, "MIN": 0.0, "MAX": 2.0 }, { "NAME": "tech", "TYPE": "float", "DEFAULT": 0.62, "MIN": 0.0, "MAX": 1.0 }, { "NAME": "scale", "TYPE": "float", "DEFAULT": 1.0, "MIN": 0.4, "MAX": 2.4 }, { "NAME": "focus", "TYPE": "point2D", "DEFAULT": [0.5, 0.5] }, { "NAME": "colorA", "TYPE": "color", "DEFAULT": [1.0, 0.48, 0.05, 1.0] }, { "NAME": "colorB", "TYPE": "color", "DEFAULT": [0.04, 0.52, 1.0, 1.0] }, { "NAME": "seed", "TYPE": "float", "DEFAULT": 3.0, "MIN": 0.0, "MAX": 20.0 } ], "PASSES": [ { "TARGET": "ink", "PERSISTENT": true, "FLOAT": true }, { "TARGET": "echoes", "PERSISTENT": true, "FLOAT": true }, {} ] }*/ float segmentDistance(vec2 p, vec2 a, vec2 b) { vec2 pa = p - a; vec2 ba = b - a; float h = clamp(dot(pa, ba) / max(dot(ba, ba), 0.00001), 0.0, 1.0); return length(pa - ba * h); } float hash11(float x) { return fract(sin(x * 127.1 + seed * 31.7) * 43758.5453); } float glyphDistance(vec2 q, float kind) { float d = 10.0; if (kind < 1.0) { d = min(segmentDistance(q, vec2(-0.055, -0.07), vec2(0.025, 0.0)), segmentDistance(q, vec2(0.025, 0.0), vec2(-0.055, 0.07))); d = min(d, segmentDistance(q, vec2(-0.005, -0.07), vec2(0.075, 0.0))); d = min(d, segmentDistance(q, vec2(0.075, 0.0), vec2(-0.005, 0.07))); } else if (kind < 2.0) { d = segmentDistance(q, vec2(-0.06, -0.075), vec2(-0.06, 0.075)); d = min(d, segmentDistance(q, vec2(-0.06, 0.075), vec2(0.055, 0.075))); d = min(d, segmentDistance(q, vec2(-0.06, -0.075), vec2(0.055, -0.075))); d = min(d, segmentDistance(q, vec2(0.015, -0.045), vec2(0.015, 0.045))); } else { d = segmentDistance(q, vec2(0.0, -0.085), vec2(0.075, 0.0)); d = min(d, segmentDistance(q, vec2(0.075, 0.0), vec2(0.0, 0.085))); d = min(d, segmentDistance(q, vec2(0.0, 0.085), vec2(-0.075, 0.0))); d = min(d, segmentDistance(q, vec2(-0.075, 0.0), vec2(0.0, -0.085))); d = min(d, segmentDistance(q, vec2(-0.04, 0.0), vec2(0.04, 0.0))); } return d; } float softKnee(float x) { float hot = max(x - 1.0, 0.0); return min(x, 1.0) + hot / (1.0 + hot); } float boxBorder(vec2 p, vec2 size) { vec2 d = abs(p) - size; float signedDistance = length(max(d, 0.0)) + min(max(d.x, d.y), 0.0); return exp(-abs(signedDistance) * 210.0); } void main() { vec2 uv = isf_FragNormCoord; vec2 px = 1.0 / RENDERSIZE; vec2 p = uv - focus; p.x *= RENDERSIZE.x / RENDERSIZE.y; p /= scale; float t = TIME * speed; if (PASSINDEX == 0) { vec2 flow = vec2( 0.7 + 0.3 * sin(p.y * 13.0 + t), 0.55 * sin(p.x * 8.0 - t * 0.8) + 0.22 * cos(p.y * 17.0 + t) ); vec2 previous = IMG_NORM_PIXEL(ink, uv - flow * (0.00135 + energy * 0.00075)).rg; vec2 injection = vec2(0.0); for (int i = 0; i < 6; i++) { float fi = float(i); float travel = fract(t * (0.055 + hash11(fi + 2.0) * 0.025) + fi / 6.0 + hash11(fi) * 0.2); vec2 center = vec2(mix(-0.58, 0.58, travel), (hash11(fi + 7.0) - 0.5) * 0.58); center.y += sin(travel * 12.0 + fi * 2.3 + t * 0.33) * 0.055; vec2 q = p - center; float angle = (hash11(fi + 12.0) - 0.5) * 1.5 + sin(t * 0.31 + fi) * 0.25; q = mat2(cos(angle), -sin(angle), sin(angle), cos(angle)) * q; float d = glyphDistance(q, mod(fi, 3.0)); float stroke = smoothstep(0.015, 0.0045, d); float spark = smoothstep(0.035, 0.0, length(q - vec2(0.07, 0.0))); if (mod(fi, 2.0) < 1.0) injection.x += stroke + spark * 0.35; else injection.y += stroke + spark * 0.35; } vec2 state = previous * decay + injection * energy * vec2(0.145, 0.13); state = vec2(softKnee(state.x), softKnee(state.y)); gl_FragColor = vec4(clamp(state, 0.0, 6.0), flow * 0.28 + 0.5); return; } if (PASSINDEX == 1) { vec3 previous = IMG_THIS_PIXEL(echoes).rgb; vec2 fresh = IMG_THIS_PIXEL(ink).rg; vec2 tail = IMG_NORM_PIXEL(ink, uv - vec2(px.x * 7.0, 0.0)).rg; vec2 splitA = IMG_NORM_PIXEL(ink, uv - vec2(px.x * 13.0, px.y * 3.0)).rg; vec2 splitB = IMG_NORM_PIXEL(ink, uv - vec2(px.x * 13.0, -px.y * 3.0)).rg; vec3 wake = vec3(fresh.x + tail.x * 0.5, fresh.y + tail.y * 0.5, max(splitA.x, splitB.y)); vec3 state = max(previous * 0.952, wake * vec3(0.68, 0.7, 0.62)); state = state / (1.0 + max(state - 1.0, 0.0)); gl_FragColor = vec4(clamp(state, 0.0, 6.0), 1.0); return; } float sliceBand = floor((p.y + 0.6) * 21.0); float sliceEpoch = floor(t * 0.72); float sliceRandom = hash11(sliceBand + sliceEpoch * 19.0 + 41.0); float sliceActive = step(0.78, sliceRandom) * tech; float sliceShift = (sliceRandom - 0.5) * 0.09 * sliceActive; vec2 signalUv = clamp(uv + vec2(sliceShift, 0.0), vec2(0.001), vec2(0.999)); vec2 direct = IMG_NORM_PIXEL(ink, signalUv).rg; vec3 echo = IMG_NORM_PIXEL(echoes, signalUv).rgb; float structure = direct.x + direct.y; float allegiance = clamp(direct.y / (structure + 0.001), 0.0, 1.0); vec3 color = mix(colorA.rgb, colorB.rgb, allegiance) * structure * 1.05; color += echo.x * colorA.rgb * 0.72 + echo.y * colorB.rgb * 0.68; color += echo.z * vec3(0.22, 0.72, 1.0) * 0.38; color += pow(max(structure - 0.75, 0.0), 2.0) * vec3(1.0, 0.9, 0.62) * 0.32; vec2 gridCoord = (p + vec2(t * 0.008, 0.0)) * vec2(24.0, 18.0); vec2 gridEdge = min(fract(gridCoord), 1.0 - fract(gridCoord)); float grid = 1.0 - smoothstep(0.018, 0.05, min(gridEdge.x, gridEdge.y)); grid *= smoothstep(0.025, 0.65, structure + echo.z) * 0.13; float frames = 0.0; float locator = 0.0; float crosshairs = 0.0; for (int i = 0; i < 6; i++) { float fi = float(i); float travel = fract(t * (0.055 + hash11(fi + 2.0) * 0.025) + fi / 6.0 + hash11(fi) * 0.2); vec2 center = vec2(mix(-0.58, 0.58, travel), (hash11(fi + 7.0) - 0.5) * 0.58); center.y += sin(travel * 12.0 + fi * 2.3 + t * 0.33) * 0.055; vec2 q = p - center; float angle = (hash11(fi + 12.0) - 0.5) * 1.5 + sin(t * 0.31 + fi) * 0.25; q = mat2(cos(angle), -sin(angle), sin(angle), cos(angle)) * q; float corners = smoothstep(0.055, 0.095, max(abs(q.x), abs(q.y))); frames += boxBorder(q, vec2(0.108, 0.112)) * corners; locator += smoothstep(0.014, 0.004, length(q - vec2(0.135, -0.112))); float dashX = step(0.48, fract((q.x + t * 0.018) * 62.0)); float dashY = step(0.48, fract((q.y - t * 0.014) * 62.0)); float horizontal = exp(-abs(q.y) * 210.0) * step(0.058, abs(q.x)) * (1.0 - step(0.16, abs(q.x))) * dashX; float vertical = exp(-abs(q.x) * 210.0) * step(0.058, abs(q.y)) * (1.0 - step(0.16, abs(q.y))) * dashY; crosshairs += horizontal + vertical; } float scanY = 0.25 * sin(t * 0.42 + seed) + 0.035 * sin(t * 1.7); float scan = exp(-abs(p.y - scanY) * 190.0); scan *= step(0.34, fract((p.x + t * 0.08) * 15.0)); float dataRail = exp(-abs(abs(p.y) - 0.405) * 230.0); dataRail *= step(0.72, fract((p.x - t * 0.05 + seed) * 23.0)); vec2 dotCell = fract((p + vec2(t * 0.006, 0.0)) * vec2(29.0, 21.0)) - 0.5; float dotId = hash11(floor((p.x + 0.7) * 29.0) + floor((p.y + 0.7) * 21.0) * 31.0); float dots = smoothstep(0.13, 0.045, length(dotCell)) * step(0.68, dotId); dots *= smoothstep(0.03, 0.72, structure + echo.z) * 0.28; float sliceEdge = exp(-abs(fract((p.y + 0.6) * 21.0) - 0.5) * 90.0) * sliceActive; vec3 techColor = mix(colorA.rgb, colorB.rgb, 0.58); color += tech * techColor * (grid + frames * 0.23 + locator * 0.42 + crosshairs * 0.18 + dots); color += tech * mix(colorA.rgb, vec3(0.85, 0.95, 1.0), 0.65) * (scan * 0.2 + dataRail * 0.16 + sliceEdge * 0.08); color = 1.0 - exp(-max(color, 0.0) * 1.25); float vignette = smoothstep(0.86, 0.2, length(p)); gl_FragColor = vec4(color * (0.38 + 0.62 * vignette), 1.0); }
Signal ID: articulated signs cross a tracked signal field with identification marks and sliced persistent wakes.
generation prompt
Create a performant multipass feedback artwork built from crisp moving glyphs, then refine it with subtle tracking frames, dot matrices, dashed crosshairs, signal rails, and sparse horizontal texture slices while keeping the symbols dominant.
export clip · render a video in your browser
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.
embed · drop this shader into any page
Renders client-side in the reader's browser (CC0 — no attribution required, but the backlink is appreciated).