SVG Zoom — vector vs frozen raster

Two WebGL2 panels magnify the same artwork (dh.svg) toward the same
focus point at the same magnification. The only thing that differs is where
each panel’s pixels come from:

The N is specifiable — drag the frozen resolution slider (4–256) to freeze
the raster at any size and watch how far you can zoom before it breaks up.

The lesson

This is the resolution-independence of vector graphics, made visible:

The two panels reach identical framing by two different routes, which is the
point worth dwelling on:

Same window, same focus — only the fidelity differs.

Controls

Modernization choices

Same conventions as the Colour Cube:

Implementation notes

Running it

ES modules and fetch do not work from file://, so serve the folder with
Vite, the same as the Colour Cube:

npm run dev

Open the printed URL (e.g. http://localhost:5173).

standalone.html is a single self-contained file with the shaders, the SVG,
and all the code inlined — it opens straight from file:// with no server, handy
for a quick look or for handing to students. The modular files below are the
version to build on.

Files

index.html          two canvases, control row, module entry point
main.mjs            controller: GL contexts, SVG rasterization, render loop, controls
zoomer.mjs          Zoomer class (DOM-free renderer; textured quad + UV zoom)
initShadersJS.mjs   two-string shader loader (unchanged, Alex Clarke 2026)
shaders/
  quad.vert.glsl    vertex shader — magnifies texcoords about the focus
  quad.frag.glsl    fragment shader — samples the image
assets/
  dh.svg            the artwork (Daryl Hepting, 2020)
standalone.html     single-file build (shaders + SVG + code inlined)