Files
shaders/build.py
T
emil28092005 27d238cbe6 Ice slab with layered plasma, two-pass refraction
Pass 1 renders eight plasma sheets into an atlas with linear depth in alpha;
pass 2 marches the refracted ray to each sheet and absorbs it by real path
length, so near and far layers separate under pointer parallax. Plasma cycle
repeats exactly every 30 s; - / = change speed.
2026-10-30 19:56:16 +03:00

50 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""Inline every *.frag next to this file into playground.html (keys 1..N switch, mouse = u_mouse)."""
import glob, json, os
here = os.path.dirname(os.path.abspath(__file__))
frags = sorted(glob.glob(os.path.join(here, "*.frag")))
names = [os.path.basename(f)[:-5] for f in frags]
srcs = [open(f).read() for f in frags]
html = """<!doctype html><html><head><meta charset=utf-8><title>shaders</title>
<style>html,body{margin:0;height:100%;background:#000;overflow:hidden}
canvas{display:block;width:100vw;height:100vh}
#osd{position:fixed;left:14px;bottom:12px;font:13px ui-monospace,monospace;color:#9bf;opacity:.75;pointer-events:none}</style>
</head><body><canvas id=c></canvas><div id=osd></div><script>
const SHADERS = __SHADERS__;
const NAMES = __NAMES__;
const VS='attribute vec2 p;void main(){gl_Position=vec4(p,0,1);}';
const c=document.getElementById('c'),osd=document.getElementById('osd');
const gl=c.getContext('webgl',{antialias:false,preserveDrawingBuffer:false});
let progs=[],cur=0,mx=0.5,my=0.5,t0=performance.now();
function sh(t,s){const o=gl.createShader(t);gl.shaderSource(o,s);gl.compileShader(o);
if(!gl.getShaderParameter(o,gl.COMPILE_STATUS)){osd.textContent='compile error: '+gl.getShaderInfoLog(o);console.error(gl.getShaderInfoLog(o));}
return o;}
for(const s of SHADERS){const pr=gl.createProgram();
gl.attachShader(pr,sh(gl.VERTEX_SHADER,VS));gl.attachShader(pr,sh(gl.FRAGMENT_SHADER,s));
gl.linkProgram(pr);progs.push(pr);}
const b=gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER,b);
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,1,1]),gl.STATIC_DRAW);
function resize(){const d=devicePixelRatio||1;c.width=innerWidth*d;c.height=innerHeight*d;}
addEventListener('resize',resize);resize();
addEventListener('mousemove',e=>{mx=e.clientX/innerWidth;my=1-e.clientY/innerHeight;});
addEventListener('keydown',e=>{if(e.key>='1'&&e.key<=String(progs.length)){cur=+e.key-1;}});
function frame(){
const pr=progs[cur];gl.useProgram(pr);
const l=gl.getAttribLocation(pr,'p');gl.enableVertexAttribArray(l);
gl.vertexAttribPointer(l,2,gl.FLOAT,false,0,0);
gl.uniform2f(gl.getUniformLocation(pr,'u_res'),c.width,c.height);
gl.uniform1f(gl.getUniformLocation(pr,'u_time'),(performance.now()-t0)/1000);
gl.uniform2f(gl.getUniformLocation(pr,'u_mouse'),mx,my);
gl.viewport(0,0,c.width,c.height);gl.drawArrays(gl.TRIANGLE_STRIP,0,4);
osd.textContent=NAMES[cur]+' ['+(cur+1)+'/'+progs.length+'] · keys 1-'+progs.length+' switch · move mouse';
requestAnimationFrame(frame);
}
frame();
</script></body></html>
"""
out = html.replace("__SHADERS__", json.dumps(srcs)).replace("__NAMES__", json.dumps(names))
open(os.path.join(here, "playground.html"), "w").write(out)
print("playground.html:", ", ".join(names))