toy = function (shader, options = {}) {
let div = html`<div>`;
let {
width = 512,
height = 512,
render = "continuous",
extra_uniforms = {}
} = options;
let canvas = DOM.canvas(width, height);
let gl = canvas.getContext("webgl", {
antialias: true
});
let regl = createRegl(gl);
let now = Date.now();
let uniforms = {
iResolution: [width, height, 1],
iFrame: 0,
iMouse: [0, 0, 0, 0],
iTime: 0
};
let inputs = {};
for (const key of Object.keys(extra_uniforms)) {
uniforms[key] = 0;
if (typeof extra_uniforms[key] == "string") {
inputs[key] = parseInput(extra_uniforms[key]);
div.append(inputs[key]);
}
}
let uniform_props = {};
for (const key of Object.keys(uniforms)) {
uniform_props[key] = regl.prop(key);
}
let draw;
let oldlog = console.log;
let error = "";
console.log = function (...args) {
error += args[0];
};
try {
draw = regl({
frag:
`
precision mediump float;
uniform vec3 iResolution;
uniform int iFrame;
uniform float iTime;
uniform vec4 iMouse;
` +
[...Object.keys(extra_uniforms)]
.map((key) => `uniform float ${key};`)
.join("\n") +
"\n" +
shader,
vert: `
attribute vec2 position;
void main () {
gl_Position = vec4(position, 0, 1);
}`,
attributes: {
position: [
[-1, -1],
[1, -1],
[1, 1],
[1, 1],
[-1, 1],
[-1, -1]
]
},
uniforms: uniform_props,
count: 6
});
} catch (e) {
error += e;
}
console.log = oldlog;
if (error != "") throw error;
let requestId = null;
function renderFrame() {
uniforms.iFrame++;
uniforms.iTime = (Date.now() - now) / 1000;
for (let key of Object.keys(extra_uniforms)) {
if (inputs[key]) {
uniforms[key] = inputs[key].value;
} else {
uniforms[key] = extra_uniforms[key]();
}
}
draw(uniforms);
}
canvas.onmousedown = canvas.onmouseup = (e) => {
uniforms.iMouse = [e.offsetX, height - e.offsetY, e.buttons, 0];
if (render != "single") renderFrame();
};
canvas.onmousemove = (e) => {
uniforms.iMouse = [e.offsetX, height - e.offsetY, e.buttons, 0];
if (render != "single" || e.buttons != 0) renderFrame();
};
invalidation.then(() => {
if (requestId) cancelAnimationFrame(requestId);
});
canvas.value = shader;
if (render == "continuous") {
function animationRender() {
renderFrame();
requestId = requestAnimationFrame(animationRender);
}
animationRender();
} else {
renderFrame();
}
div.append(canvas);
return div;
}