demo · v138
WebGL texture feed
The 2D canvas use case is the obvious one. The interesting one is using a live DOM subtree as a WebGL texture — texElementImage2D() uploads the rasterised element straight into a GPU texture, so you can wrap a real form, a live <input>, or a styled article onto a 3D mesh.
Behind a flag: ships in Chrome 138 with
chrome://flags/#enable-experimental-web-platform-features. Fallback uses a striped procedural texture so the geometry still spins.
probing texElementImage2D…
DOM subtree (real HTML — type into it)
Live HTML subtree
This is an actual div. Try focusing the input — text caret, selection, focus ring all behave the way they should.
WebGL canvas — texture sampled from above
The shape of the API
const canvas = document.getElementById('gl');
canvas.layoutSubtree = true; // opt the canvas in
const gl = canvas.getContext('webgl2');
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
// upload the live DOM element into the GPU texture
gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA,
gl.RGBA, gl.UNSIGNED_BYTE,
document.getElementById('ui'));
canvas.addEventListener('paintsubtree', () => {
gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA,
gl.RGBA, gl.UNSIGNED_BYTE,
document.getElementById('ui'));
});
What's happening
- Three new primitives ship:
canvas.layoutSubtree = true(opt-in),drawElement/texElementImage2D/copyElementImageToTexture(upload), and apaintsubtreeevent (re-upload signal). - The DOM subtree is laid out and rasterised by the engine. Then it lands in a 2D context, a WebGL texture, or a WebGPU texture.
- Crucially, the original subtree is still in the page. It accepts focus, keyboard, AT — everything you lose with
html2canvas. - For this demo: the WebGL canvas mounts a textured quad that spins. The texture comes from the live left pane — type into the input and the texture updates next frame.