an algorithm for computing winding & anti-aliasing of 2D vector shapes
194
stars
51
commits
JavaScript
primary language
Aug 13, 2026
updated
Code and demos for windfoil, a method for filling 2D vector shapes built from quadratic-Bézier contours, by computing winding and analytic anti-aliasing per-pixel in a fragment shader. The algorithm was designed to improve upon the public Slug Algorithm for certain uses cases.
🚩 This builds on prior work (Slug, Vello, Pathfinder, font-rs and others), and may or may not be a novel algorithm. The core of the algorithm was designed by Code Claude on Fable after a ~1.5 hour uninterrupted session within a larger codebase I am working on, although it required several more hours and design/code iterations to tune performance and bugs (see How This Came About). It's entirely possible this algorithm collides with an existing technique in its memory, or perhaps even a patent. After searching, I haven't been able to find any other algorithms or code that approaches vector rendering in the same way, but more research would be needed to be sure, so use this at your own risk.
You can see a demo of this here:
https://texel-org.github.io/windfoil/
Requires Deno 2.x on a machine with a WebGPU-capable GPU.
# renders a PNG in output/
deno task render
# compare against point-sampled box filter, Skia, and Slug (synthetic shapes + glyphs a–z)
deno task validate
# serve the demo, then open http://localhost:8080/
# (or http://localhost:8080/tools/validate/ to run the validation suite against
# the browser's own canvas2d rasterizer)
deno task serve
Note: this repo refers to "Skia" but is actually using @napi-rs/canvas as a reference, which uses Skia under the hood.
This README was written by me, but most of the code and other documentation in the repo was produced by agents at my direction.
docs/ALGORITHM.md — the algorithmdocs/NOTES.md — some additional properties of the algorithm I've found interesting for my own usessrc/windfoil.wgsl — the shader: the winding-integral box filter + the row-band gathersrc/bands.js — the row-band acceleration structuresrc/font.js — glyph outlines + metrics from the bundled font (using opentype.js)bench/ — a windfoil-vs-Slug WebGPU benchmarks and acceleration notesTo provide a little context, I have been working for some weeks now on a 2D vector engine that uses the Slug Algorithm (which is great, but primarily developed for text and icons). My goal has been "perfectly" anti-aliased vector graphics at all resolutions for high quality print artwork (e.g. 30k x 30k 16-bit PNG files), while supporting a range of complex paths, strokes, and per-pixel effects for generative art. You can see two demos of the engine here and here, alongside some other posts I've made on X/Twitter about it.
I tasked Fable with solving some problems I was encountering, and it was able to work within the large codebase I had been developing (I had a number of profilers, fuzzers and harnesses already in place across Rust/WASM, JS, Figma's renderer, and Skia via @napi-rs/canvas). Some notes & findings:
./bench/README.md. Windfoil performs comparably, sometimes slower, sometimes faster, depending on the scene and view.docs/NOTES.mdI've left much of the LLM-generated documents and code alone in this repo, although it has gone through many rounds of iterations (the first draft of the algorithm had various bugs and issues). If this is truly a novel approach, which I am still not entirely sure of, it does present to me an interesting example of AI interpolating and recombining existing ideas to form something new, and as such it seems fitting to let the AI mostly speak for itself in some of the code & documents (em dashes and all). The original name that Fable gave the algorithm was "Area Algorithm," which felt a little dull. I've gone with windfoil, a sport I've never done but would like to try one day. I also like the tie-in with the winding computation, and the light and airy properties the term evokes in my mind.
See the ./bench folder for full results, but at a glance: Slug is often faster when rendering minified shapes (i.e. zooming out, drawing small things), and windfoil tends to be marginally faster when shapes take up more of the viewport (i.e. zoomed in).
If you reference this work, you can cite it as:
Matt DesLauriers. Windfoil: per-pixel winding and analytic anti-aliasing for 2D vector shapes. 2026. https://github.com/texel-org/windfoil
@misc{deslauriers2026windfoil,
author = {DesLauriers, Matt},
title = {Windfoil: per-pixel winding and analytic anti-aliasing for 2D vector shapes},
year = {2026},
howpublished = {\url{https://github.com/texel-org/windfoil}}
}
Apache-2.0 — see LICENSE. This repository bundles the Lato font (SIL OFL 1.1), see
assets/OFL.txt.
51 commits
JavaScript
86.6%
WGSL
10.3%
HTML
3.0%
an algorithm for computing winding & anti-aliasing of 2D vector shapes
194
stars
51
commits
JavaScript
primary language
Aug 13, 2026
updated
Code and demos for windfoil, a method for filling 2D vector shapes built from quadratic-Bézier contours, by computing winding and analytic anti-aliasing per-pixel in a fragment shader. The algorithm was designed to improve upon the public Slug Algorithm for certain uses cases.
🚩 This builds on prior work (Slug, Vello, Pathfinder, font-rs and others), and may or may not be a novel algorithm. The core of the algorithm was designed by Code Claude on Fable after a ~1.5 hour uninterrupted session within a larger codebase I am working on, although it required several more hours and design/code iterations to tune performance and bugs (see How This Came About). It's entirely possible this algorithm collides with an existing technique in its memory, or perhaps even a patent. After searching, I haven't been able to find any other algorithms or code that approaches vector rendering in the same way, but more research would be needed to be sure, so use this at your own risk.
You can see a demo of this here:
https://texel-org.github.io/windfoil/
Requires Deno 2.x on a machine with a WebGPU-capable GPU.
# renders a PNG in output/
deno task render
# compare against point-sampled box filter, Skia, and Slug (synthetic shapes + glyphs a–z)
deno task validate
# serve the demo, then open http://localhost:8080/
# (or http://localhost:8080/tools/validate/ to run the validation suite against
# the browser's own canvas2d rasterizer)
deno task serve
Note: this repo refers to "Skia" but is actually using @napi-rs/canvas as a reference, which uses Skia under the hood.
This README was written by me, but most of the code and other documentation in the repo was produced by agents at my direction.
docs/ALGORITHM.md — the algorithmdocs/NOTES.md — some additional properties of the algorithm I've found interesting for my own usessrc/windfoil.wgsl — the shader: the winding-integral box filter + the row-band gathersrc/bands.js — the row-band acceleration structuresrc/font.js — glyph outlines + metrics from the bundled font (using opentype.js)bench/ — a windfoil-vs-Slug WebGPU benchmarks and acceleration notesTo provide a little context, I have been working for some weeks now on a 2D vector engine that uses the Slug Algorithm (which is great, but primarily developed for text and icons). My goal has been "perfectly" anti-aliased vector graphics at all resolutions for high quality print artwork (e.g. 30k x 30k 16-bit PNG files), while supporting a range of complex paths, strokes, and per-pixel effects for generative art. You can see two demos of the engine here and here, alongside some other posts I've made on X/Twitter about it.
I tasked Fable with solving some problems I was encountering, and it was able to work within the large codebase I had been developing (I had a number of profilers, fuzzers and harnesses already in place across Rust/WASM, JS, Figma's renderer, and Skia via @napi-rs/canvas). Some notes & findings:
./bench/README.md. Windfoil performs comparably, sometimes slower, sometimes faster, depending on the scene and view.docs/NOTES.mdI've left much of the LLM-generated documents and code alone in this repo, although it has gone through many rounds of iterations (the first draft of the algorithm had various bugs and issues). If this is truly a novel approach, which I am still not entirely sure of, it does present to me an interesting example of AI interpolating and recombining existing ideas to form something new, and as such it seems fitting to let the AI mostly speak for itself in some of the code & documents (em dashes and all). The original name that Fable gave the algorithm was "Area Algorithm," which felt a little dull. I've gone with windfoil, a sport I've never done but would like to try one day. I also like the tie-in with the winding computation, and the light and airy properties the term evokes in my mind.
See the ./bench folder for full results, but at a glance: Slug is often faster when rendering minified shapes (i.e. zooming out, drawing small things), and windfoil tends to be marginally faster when shapes take up more of the viewport (i.e. zoomed in).
If you reference this work, you can cite it as:
Matt DesLauriers. Windfoil: per-pixel winding and analytic anti-aliasing for 2D vector shapes. 2026. https://github.com/texel-org/windfoil
@misc{deslauriers2026windfoil,
author = {DesLauriers, Matt},
title = {Windfoil: per-pixel winding and analytic anti-aliasing for 2D vector shapes},
year = {2026},
howpublished = {\url{https://github.com/texel-org/windfoil}}
}
Apache-2.0 — see LICENSE. This repository bundles the Lato font (SIL OFL 1.1), see
assets/OFL.txt.
51 commits
JavaScript
86.6%
WGSL
10.3%
HTML
3.0%