Created
February 25, 2026 12:52
-
-
Save Staars/766701fe7e6a0ee7afd6f4ba44250c44 to your computer and use it in GitHub Desktop.
GL analyzer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html><head><meta charset='utf-8'><title>16-Band Visualizer</title> | |
| <style>body{margin:0;overflow:hidden;background:#000}canvas{display:block}</style> | |
| </head><body> | |
| <canvas id='c'></canvas><script> | |
| // ================================================================ | |
| // TUNING | |
| var AMP = 2.75; // wave height multiplier (try 1.0 .. 5.0) | |
| var SPEED = 5.6; // scroll rate rad/s (try 0.1 .. 2.0) | |
| var HZ = 50; // input packet rate Hz (50=dev 5x, 10=real) | |
| // ================================================================ | |
| var c=document.getElementById('c'),gl=c.getContext('webgl2'); | |
| if(!gl)alert('no webgl2'); | |
| function rsz(){var d=devicePixelRatio||1;c.width=innerWidth*d;c.height=innerHeight*d;c.style.width=innerWidth+'px';c.style.height=innerHeight+'px';gl.viewport(0,0,c.width,c.height);} | |
| window.onresize=rsz;rsz(); | |
| var TW=512,TH=16,head=0; | |
| var tex=gl.createTexture(); | |
| gl.activeTexture(gl.TEXTURE0); | |
| gl.bindTexture(gl.TEXTURE_2D,tex); | |
| gl.texImage2D(gl.TEXTURE_2D,0,gl.R32F,TW,TH,0,gl.RED,gl.FLOAT,new Float32Array(TW*TH)); | |
| gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.REPEAT); | |
| gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE); | |
| gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR); | |
| gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR); | |
| function push(b16){ | |
| var n=b16.length,t=new Float32Array(n),o=new Float32Array(n); | |
| for(var i=0;i<n;i++)t[i]=b16[Math.max(0,i-1)]*.2+b16[i]*.6+b16[Math.min(n-1,i+1)]*.2; | |
| for(var i=0;i<n;i++)o[i]=t[Math.max(0,i-1)]*.2+t[i]*.6+t[Math.min(n-1,i+1)]*.2; | |
| gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,tex); | |
| gl.texSubImage2D(gl.TEXTURE_2D,0,head,0,1,TH,gl.RED,gl.FLOAT,o); | |
| head=(head+1)%TW; | |
| } | |
| function mksh(t,s){var x=gl.createShader(t);gl.shaderSource(x,s);gl.compileShader(x);if(!gl.getShaderParameter(x,gl.COMPILE_STATUS))console.error(gl.getShaderInfoLog(x));return x;} | |
| var VS='#version 300 es\n'+'layout(location=0)in vec2 p;\n'+'void main(){gl_Position=vec4(p,0.,1.);}\n'; | |
| var FS='#version 300 es\n'+'precision highp float;\n'+'uniform float iTime;uniform vec2 iRes;uniform sampler2D H;uniform float F;uniform float SC;uniform float AMP;\n'+'out vec4 fragColor;\n'+'#define pal(t,a,b,c,d) (a+b*cos(6.28318*(c*t+d)))\n'+'#define S(x,y,z) smoothstep(x,y,z)\n'+'float bamp(float sx,float ln){\n'+' float cf=mod(F-1.0-(1.0-sx)*511.0,512.0);\n'+' float u=(cf+0.5)/512.0;\n'+' float row=clamp(ln+8.0,0.0,15.0);\n'+' float v=(row+0.5)/16.0;\n'+' return clamp(texture(H,vec2(u,v)).r,0.0,1.0);\n'+'}\n'+'float w(float x,float sx,float ln){\n'+' x*=5.0;\n'+' float t=ln*0.5+SC;\n'+' float amp=bamp(sx,ln);\n'+' return(sin(x*.25+t)*5.+sin(x*4.5+t*3.)*.2+sin(x+t*3.)*2.3+sin(x*.8+t*1.1)*2.5)*AMP*(0.05+amp*0.95);\n'+'}\n'+'void main(){\n'+' vec2 r=iRes,st=(gl_FragCoord.xy*2.0-r)/r.y;\n'+' float sx=gl_FragCoord.x/r.x;\n'+' float th=.05,sm=28./r.y+.85*length(S(vec2(.01,.2),vec2(2.,.7),abs(st)));\n'+' float cc=0.,n=floor(st.y/.1),y=fract(st.y/.1);\n'+' vec3 clr=vec3(0.);\n'+' for(float i=-5.;i<5.;i++){\n'+' float ln=n-i,f=w(st.x,sx,ln)-y-i;\n'+' cc=mix(cc,0.,S(-.3,abs(st.y),f));\n'+' cc+=S(th+sm,th-sm,abs(f))*(1.-abs(st.y)*.75)+S(5.5-abs(f*.5),0.,f)*.25;\n'+' clr=mix(clr,pal(sin(ln*.15),vec3(.5),vec3(.5),vec3(.27),vec3(0.,.05,.15))*cc,S(-.3,abs(st.y),f));\n'+' }\n'+' fragColor=vec4(clr,1.0);\n'+'}\n'; | |
| var prog=gl.createProgram(); | |
| gl.attachShader(prog,mksh(gl.VERTEX_SHADER,VS)); | |
| gl.attachShader(prog,mksh(gl.FRAGMENT_SHADER,FS)); | |
| gl.linkProgram(prog); | |
| if(!gl.getProgramParameter(prog,gl.LINK_STATUS))console.error(gl.getProgramInfoLog(prog)); | |
| gl.useProgram(prog); | |
| var vb=gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER,vb); | |
| gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,1,1]),gl.STATIC_DRAW); | |
| gl.enableVertexAttribArray(0);gl.vertexAttribPointer(0,2,gl.FLOAT,false,0,0); | |
| var uT=gl.getUniformLocation(prog,'iTime'); | |
| var uR=gl.getUniformLocation(prog,'iRes'); | |
| var uH=gl.getUniformLocation(prog,'H'); | |
| var uF=gl.getUniformLocation(prog,'F'); | |
| var uSC=gl.getUniformLocation(prog,'SC'); | |
| var uAMP=gl.getUniformLocation(prog,'AMP'); | |
| gl.uniform1i(uH,0); | |
| var NB=16,ph=new Float32Array(NB),sp=new Float32Array(NB),va=new Float32Array(NB); | |
| for(var b=0;b<NB;b++){ph[b]=Math.random()*6.28;sp[b]=0.4+Math.random()*1.2;} | |
| function dummy(){ | |
| var t=performance.now()*.001,pkt=new Float32Array(NB); | |
| for(var b=0;b<NB;b++){ | |
| va[b]=Math.max(0,Math.min(1,va[b]*.75+(0.5+0.45*Math.sin(ph[b]+t*sp[b]*.3))*.25+(Math.random()-.5)*.1)); | |
| pkt[b]=va[b]; | |
| } | |
| push(pkt); | |
| } | |
| setInterval(dummy,1000/HZ); | |
| var sc=0.0,t0=performance.now(),pt=t0; | |
| function loop(now){ | |
| var dt=Math.min((now-pt)*.001,.05);pt=now; | |
| sc+=SPEED*dt; | |
| gl.useProgram(prog);gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,tex); | |
| gl.uniform1f(uT,(now-t0)*.001); | |
| gl.uniform2f(uR,c.width,c.height); | |
| gl.uniform1f(uF,head); | |
| gl.uniform1f(uSC,sc); | |
| gl.uniform1f(uAMP,AMP); | |
| gl.drawArrays(gl.TRIANGLE_STRIP,0,4); | |
| requestAnimationFrame(loop); | |
| } | |
| requestAnimationFrame(loop); | |
| </script></body></html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment