Skip to content

Instantly share code, notes, and snippets.

@spite
Last active March 20, 2021 13:51
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save spite/6675ac4622a39cc7a75449215603fe4d to your computer and use it in GitHub Desktop.
Save spite/6675ac4622a39cc7a75449215603fe4d to your computer and use it in GitHub Desktop.
WebGL in SVG via foreignObject
Display the source blob
Display the rendered blob
Raw
<svg id="container" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000" style="background: white;">
<style>
text {
user-select: none;
-webkit-user-select: none; /* lol */
}
</style>
<foreignObject x="0" y="0" width="100%" height="100%">
<span xmlns="http://www.w3.org/1999/xhtml">
<canvas id="output"></canvas>
</span>
</foreignObject>
<script>
const fO = document.querySelector('foreignObject');
const canvas = fO.querySelector('#output');
const gl = canvas.getContext('webgl');
function resize() {
canvas.width = 1000;//window.innerWidth;
canvas.height = 1000;//window.innerHeight;
}
resize();
var v = `attribute vec2 aVertexPosition;
void main() {
gl_Position = vec4(aVertexPosition, 0.0, 1.0);
}`;
var f = `#ifdef GL_ES
precision highp float;
#endif
uniform vec4 uColor;
#define PI 3.14159
void main() {
float v = 0.0;
float u_k = .01;
vec2 c = gl_FragCoord.xy * u_k - u_k/2.0;
v += sin((c.x+uColor.b));
v += sin((c.y+uColor.b)/2.0);
v += sin((c.x+c.y+uColor.b)/2.0);
c += u_k/2.0 * vec2(sin(uColor.b/3.0), cos(uColor.b/2.0));
v += sin(sqrt(c.x*c.x+c.y*c.y+1.0)+uColor.b);
v = v/2.0;
vec3 col = vec3(1, sin(PI*v), cos(PI*v));
gl_FragColor = vec4(col*.5 + .5, 1);
}`;
var vs = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vs, v);
gl.compileShader(vs);
var fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fs, f);
gl.compileShader(fs);
program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
var aspect = canvas.width / canvas.height;
var vertices = new Float32Array([
-0.6, 0.4*aspect, 0.6, 0.4*aspect, 0.6,-0.4*aspect,
-0.6, 0.4*aspect, 0.6,-0.4*aspect, -0.6,-0.4*aspect
]);
vbuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
itemSize = 2;
numItems = vertices.length / itemSize;
program.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition");
gl.enableVertexAttribArray(program.aVertexPosition);
gl.vertexAttribPointer(program.aVertexPosition, itemSize, gl.FLOAT, false, 0, 0);
const output = document.querySelector('#output');
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearColor(1, 1, 1, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.useProgram(program);
gl.bindBuffer(gl.ARRAY_BUFFER, vbuffer);
program.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition");
gl.enableVertexAttribArray(program.aVertexPosition);
gl.vertexAttribPointer(program.aVertexPosition, itemSize, gl.FLOAT, false, 0, 0);
async function render() {
program.uColor = gl.getUniformLocation(program, "uColor");
gl.uniform4fv(program.uColor, [0.0, 0.0, .001 * performance.now(), 1.0]);
gl.drawArrays(gl.TRIANGLES, 0, numItems);
requestAnimationFrame(render);
};
render();
</script>
</svg>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment