Modern GPUs can draw billions of triangles per second. That’s great for 3D artists and because they don’t have to work nearly as hard to optimize their assets.
But there’s a distinct charm in the aesthetics born from simplicity.
Keeping an image readable and recognizable while stripping away detail is a fun challenge. Done well, the results are often striking:
A few years ago I wrote a script that stylizes any image as low-poly. Here’s a few samples processed through that script:
The first version of this generator (Kon) was Python-based, using numpy
, opencv
, and scipy
. It got the job done, but it was slow - about 15 seconds per image.
I figured I could do better, so I revisited the generator to do a Rust rewrite.
How it works
I’ll start with this beetle I photographed at MacRitchie reservoir:
Step 1: Smart Point Sampling
The key to a good low-poly image is choosing the right points. Instead of random sampling, Kon uses a Sobel filter to focus on edges and important features.
The Sobel gradient of an image highlights changes in intensity - it’s bright where there’s high-frequency detail and dark where the intensity doesn’t change much. Essentially, it acts like an edge detector.
To further emphasize the most salient edges, I also raise the contrast on the Sobel gradient by exponentiating it:
We then run weighted random sampling over the gradient image to pick a set of points to act as the basis for our low-poly image’s polygons:
Step 2: Delaunay Triangulation
Once the points are picked, they’re connected with Delaunay triangulation, which ensures well-formed triangles without overlap.
- Built with the
spade
crate for efficient triangulation. - Edge handling to prevent artifacts or gaps.
- Parallelized with Rayon for speed.
Step 3: Coloring the Polygons
Each triangle’s color is determined using:
- K-Means clustering for dominant colors.
- Median Cut for color quantization.
- Mean color fallback for tiny triangles.
To make sure everything worked, I generated debug images at different stages. This made it easy to spot issues like uneven point distribution and triangulation artifacts.
What’s Next?
Kon is a lot faster now, but there’s still a lot missing and many ways to improve it. Here’s a few things I’ve been thinking about:
- Manual Point Placement – Let users tweak key points.
- WASM GUI – A browser-based interactive tool.
- More Polygon Types – Triangles are great, but what about hexagons? And other shapes?
- Selective Effects – Low-poly only on certain parts of an image.
- GPU Acceleration – CUDA or Vulkan for real-time processing.
- Low-Poly Video – Extending the approach to moving frames.
Inspiration
When I revisited this project, I found other great takes on low-poly generation:
- DarkForte’s CUDA version – A GPU-accelerated approach with similar principles.
- r/lowpoly2d – A goldmine of stylized low-poly art.
- r/generative – Algorithmic art at its best.
- r/proceduralgeneration – A deep dive into procedural techniques.
If you want to try the generator, check out the GitHub repo