Reference · Viewing
precision highp float;
uniform float iTime;
uniform vec3 iResolution;
uniform vec2 iPointer;
uniform sampler2D iChannel0;
uniform sampler2D iCamera;
uniform float iBpm;
uniform float iPlaying;
uniform float iAudioVolume;
float hash1(float n){ return fract(sin(n*12.9898)*43758.5453); }
float spec(float f){
return texture2D(iChannel0, vec2(clamp(f,0.001,0.999), 0.25)).r;
}
void main(){
vec2 f = gl_FragCoord.xy / iResolution.xy;
vec2 uv = (gl_FragCoord.xy - 0.5*iResolution.xy)/iResolution.y;
// audio bands
float bass = (spec(0.025)+spec(0.045)+spec(0.07))*0.3333;
float mid = (spec(0.18)+spec(0.25)+spec(0.32))*0.3333;
float treb = (spec(0.55)+spec(0.68)+spec(0.82))*0.3333;
float gate = mix(0.22, 1.0, iPlaying);
bass *= gate; mid *= gate; treb *= gate;
float vol = iAudioVolume * gate + (1.0-gate)*0.15;
// trusted beat clock
float bps = max(iBpm, 30.0)/60.0;
float bt = iTime*bps;
float bid = floor(bt);
float bph = fract(bt);
float punch = exp(-bph*5.0);
float swell = exp(-bph*2.0);
float bh = hash1(bid+7.0);
float bh2 = hash1(bid*1.7+3.0);
float dirSign = bh > 0.5 ? 1.0 : -1.0;
// pointer steers prism core
vec2 asp = vec2(iResolution.x/iResolution.y, 1.0);
vec2 core = (iPointer-0.5)*asp*0.7;
core += 0.08*vec2(sin(iTime*0.4), cos(iTime*0.33));
vec2 p = uv - core;
float R = length(p);
float A = atan(p.y, p.x+1e-5);
// spin: slow drift + per-beat snap with overshoot
float spin = iTime*0.12*dirSign + float(int(bid))*0.22*dirSign;
spin += punch*0.55*dirSign*(0.4+0.6*bh2)*(0.3+bass*2.0);
float twist = (0.9*mid + 0.5*vol)/(R+0.35);
twist += vol*0.6*sin(R*7.0 - bt*3.14159 + bh*6.28);
twist += treb*0.8*sin(A*3.0+iTime*2.0);
A += spin + twist;
// prism folding: mirrored kaleido segments, count flips every 4 beats
float segs = 7.0 + mod(bid*0.5, 4.0)*2.0; // 7,9,11,13 cycle
segs += floor(mid*3.0);
float seg = 6.2831853/segs;
float af = mod(A, seg*2.0);
af = abs(af-seg); // 0..seg mirrored
float edgeD = min(af, seg-af);
// radial breathing locked to beat
float zoomR = R*(1.0 - 0.28*punch*(0.25+bass*1.6) - 0.10*swell*mid);
zoomR += 0.02*sin(R*18.0 - iTime*3.0)*vol;
vec2 kdir = vec2(cos(af), sin(af));
// alternate rings flip orientation for woven look
float ringId = floor(zoomR*4.0 + bh*2.0);
if(mod(ringId,2.0)>0.5) kdir.x = -kdir.x;
vec2 kp = kdir*zoomR;
float zscale = 1.05 + bass*1.1 + punch*0.35 + vol*0.5;
vec2 base = kp*zscale;
// liquid wobble scaled by master volume
float wamp = 0.04 + vol*0.22 + mid*0.08;
vec2 wob;
wob.x = sin(base.y*9.0 + iTime*1.7 + bid)*cos(base.x*7.0 - iTime*1.3);
wob.y = cos(base.x*8.0 - iTime*1.9 + bh*6.28)*sin(base.y*6.0 + iTime*1.1);
base += wob*wamp*0.35;
// mirrored tile the live video so folds never go black
vec2 tile = vec2(0.5)+base;
tile = abs(fract(tile*0.5)*2.0-1.0);
tile = 1.0-abs(1.0-tile*1.0);
vec2 cuv = fract(tile);
cuv = clamp(cuv, 0.001, 0.999);
// radial chromatic split of the video
vec2 rad = (R>1e-4) ? p/R : vec2(1.0,0.0);
float ca = 0.006 + treb*0.025 + punch*0.014*(0.3+bass);
vec3 vid;
vid.r = texture2D(iCamera, fract(cuv + rad*ca*(0.5+R))).r;
vid.g = texture2D(iCamera, cuv).g;
vid.b = texture2D(iCamera, fract(cuv - rad*ca*(0.5+R))).b;
// keep luma lively even if camera is dark
float vl = dot(vid, vec3(0.299,0.587,0.114));
vec3 synth = 0.5+0.5*cos(iTime*0.7+vec3(0.0,2.1,4.2)+R*6.0+af*4.0);
vid = mix(synth*0.35, vid, clamp(vl*4.0+0.35,0.0,1.0));
// segment seams flash on the beat
float seam = exp(-edgeD*38.0/(0.15+R*1.4));
vec3 seamCol = mix(vec3(0.1,0.9,1.0), vec3(1.0,0.25,0.75), bh2);
seamCol = mix(seamCol, vec3(1.0,0.95,0.5), punch*0.6);
vid += seamCol*seam*(0.15+punch*1.4*(0.3+treb*2.0)+treb*0.3);
// spectrum sparks along radius: thin equalizer arcs
float fq = clamp(af/seg*0.6 + R*0.45, 0.01, 0.95);
float mag = spec(fq);
float ring = smoothstep(0.025,0.0,abs(R-(0.22+mag*0.55+punch*0.06))-0.008);
vid += vec3(1.0,0.9,0.6)*ring*(0.4+punch);
// beat vignette pump + pointer spotlight
float vig = smoothstep(1.45, 0.25, length(uv*vec2(1.0,1.0)));
float spot = exp(-dot(p,p)*6.0);
vec3 col = vid*(0.55+0.65*vig);
col += vid*spot*(0.25+punch*0.6);
col *= 0.75 + 0.5*punch*gate + vol*0.3;
// gentle filmic lift
col = col/(1.0+0.25*dot(col,col));
col = pow(clamp(col,0.0,1.0), vec3(0.92));
gl_FragColor = vec4(col, 1.0);
}