Fork me on GitHub

Procedural pixel art rendering

Vegard Nossum — @vegard_no

In some sense, pixel art is all about communicating meaningfully despite the limitations of the medium, specifically the limited spatial resolutions and limited palettes.

This article is about rendering pixel art procedurally, for example rendering 3D scenes and objects at lower resolutions but arriving at a result that mimics pixel art rather than being pure reductions.

Texture filtering

When rendering pixel art on modern screens with high resolutions, we typically need to scale it up. There are many ways to do this.

Most hardware and modern rendering frameworks support several types of texture filtering; for example, in OpenGL, you can specify GL_NEAREST or GL_LINEAR for magnifications. So which texture filter should we use when magnifying pixel art?

It turns out that neither of the default options are really good for pixel art. “Nearest neighbour” filtering creates unevenly-sized pixels at non-integer factors of magnification:

Zoom:

“Linear” filtering adds a blurring effect which is too strong and often unwanted for pixel art. It also has a tendency to wash out some of the colour:

Zoom:

What we want is instead something that preserves the appearance of a square pixel by smoothing only the borders between them, rather than smoothing across the whole pixel:

Zoom:

This also has the effect that scaling at exact integer factors gives us perfectly crispy pixels.

Of course, some people may occasionally want their pixel art a little blurred, to emulate the CRT effect. That is probably best implemented as a screen effect after compositing the scene, but before scaling it up to the full screen.

Dithering gradients

Gradients

Dithering is when you alternate between two colours to create the impression of a gradient. There are so many different ways to do dithering! There is random dithering, patterned dithering, ordered dithering, etc. And we can also create variations by changing the parameters of these algorithms. One of my favourite variations of ordered dithering allows us to interpolate between plain thresholding and full ordered dithering; try playing with the “sharpness” parameter below:

Dithering texture:

Angle:
Width:
Levels:
Sharpness:

Spheres

Grab the sphere and drag it to change the position of the light source!

Dithering texture:

Levels:
Sharpness:

Simply by using different dithering techniques on different materials we can really make a scene come alive.

Lines

One of the most basic primitives is the straight line.

Angle:
Thickness:
Levels:
Antialiasing:
Threshold:
Gamma:
Scale: