Pixel Art
Pixel art is deceptively challenging to get right. There are a few rendering artifacts that can plague pixel art games in this guide hopefully we'll get you to the prettiest possible pixel art.
Basic Approach: Nearest Neighbor and No Antialiasing
This is the first approach that most people try, and for some games might be fine if you are snapping to whole pixel values and scale your graphics by integer amounts. In fact many games are shipped this way.
If you set Excalibur to new ex.Engine({antialiasing: false})
this is what you'll get!
Cons: Artifacts
Using the basic approach comes with some downsides: shimmering artifacts (inconsistent line widths) and jaggies when rotating objects.
Solution might be to use new ex.Engine({pixelRatio: 3})
to "upscale" lower resolutions to more pixels.
New Approach: Texture Filtering, Scaling, and special Antialiasing
Excalibur has a special pixel art mode that will put you into this mode released in v0.29.0!
typescript
const game = new ex.Engine({pixelArt: true // and that's it!});
typescript
const game = new ex.Engine({pixelArt: true // and that's it!});
If you have very low resolutions less than 500x500, you might want to consider artificially scaling the graphics by setting pixelRatio: 2
or pixelRatio: 3
this increases the internal resolution (effectively up-scaling) giving Excalibur more pixels to work with and smooth. This produces more pleasing results when simulating a very low res game
Another strategy might be using the game.currentScene.zoom
to zoom into your pixel art
This will set a few presets in excalibur, this above setting is equivalent to the following
typescript
const game = new ex.Engine({antialiasing: {pixelArtSampler: true, // turns on the sub-pixel shader for pixel artnativeContextAntialiasing: false, // turns off canvas aamultiSampleAntialiasing: true, // turns on msaa which smooths quad boundariesfiltering: ImageFiltering.Blended, // hints the image loader to use blended filteringcanvasImageRendering: 'auto' // applies the 'auto'-matic css to the canvas CSS image-rendering}})
typescript
const game = new ex.Engine({antialiasing: {pixelArtSampler: true, // turns on the sub-pixel shader for pixel artnativeContextAntialiasing: false, // turns off canvas aamultiSampleAntialiasing: true, // turns on msaa which smooths quad boundariesfiltering: ImageFiltering.Blended, // hints the image loader to use blended filteringcanvasImageRendering: 'auto' // applies the 'auto'-matic css to the canvas CSS image-rendering}})
This is great article explaining the approach
Here is a shader toy demonstrating
- Shader Toy showing https://www.shadertoy.com/view/mdSXWy