A Brief History of Computer Graphics
Back in the 1980’s, computers were first entering the mainstream. They were finally small enough and cheap enough for consumers to purchase and bring into their homes. A popular home computer was the Commodore 64. And a popular video game console was the Nintendo Entertainment System (NES).
These machines were not nearly as powerful as the machines of today. Modern day computers and consoles have dedicated GPUs with their own separate VRAM. In computers in the 1980s, the video chip used the same memory as the CPU. A typical home computer system at the time only had 16 kilobytes of RAM, or 32 kilobytes on higher end systems. 64 kilobytes of RAM was not unheard of, but very expensive.
And even though the resolution was low on these machines, at least compared to modern standards, it took an incredible amount of the computer’s memory just to display colors. To give you an idea of what a 16 color pallette looks like, here is an image of a parrot. The image on the left is 4-bit color (16 total colors) and the image on the right is 8-bit color (256 total colors).
So computer engineers needed to find workarounds in order to display better images on this limited hardware. One such method was the use of "color cells". Groups of pixels were divided up into 8 x 8 sections called cells. And while each cell only had two colors, a background and a foreground color, each cell could have its own different two colors. And this consumed only 9 kilobytes of RAM, for a huge step up in color options compared to the 8 kilobyte black and white option.
Here is one such image made using this technique.
If you zoom in and study the image, you can see each 8 x 8 group of pixels only contains two colors. The artist, Oliver Lindau, was very careful to hide the seams where different color cells bordered each other.
There was a different rendering option as well known as multicolor mode. It halved the screen resolution by making two adjacent pixels share the same data. But this allowed every cell to now support four different colors for the same 9 kilobytes of RAM.
An Art Style is Born
From the limitations of this 1980’s hardware, emerged an aesthetic, a style of art which is commonly referred to as "pixel art".
What is considered pixel art can vary widely in the modern day. But some core tenets of established themselves over the years. Because pixel art is done in such a limited resolution and limited color palette, the placement of each pixel and it’s color is fundamentally intentional. An errant pixel will stand out as "wrong" even to the untrained eye.
Because of the limited color palette, smooth transitions between two colors are done with a technique known as dithering. Pixels of one color are alternated in a pattern with another color, until the transition to another color is complete. Dithering can be used to create shading and other lighting effects.
Some styles of pixel art have strong lines. Edges will be noticeably marked by thick black lines. The lines can help differentiate different parts of a character that have otherwise identical coloring.
Some styles of pixel art choose to pursue a specific or unique aesthetic. Others wish to emulate the exact hardware limitations of yore, and work with the same resolutions and color palettes of older games.
Using Pixel Art with Pixel-Perfect 2D Rendering in Godot
Godot’s default settings for 2D games are suited for high resolution art to be displayed on modern high resolution monitors. Sprites are anti-aliased and compressed by default, which will ruin the aesthetic of art assets intended to be presented as pixel art.
Choosing Your Resolution and Aspect Ratio
Setting the resolution in your game is an important first step. If you are looking to emulate a specific classic console, use that same resolution.
Nintendo Entertainment System (NES) – 256 x 240
Commodore 64 – 320 x 200
Super Nintendo Entertainment System (SNES) – 256 x 224
An important consideration is the aspect ratio. Older consoles were designed to run on older televisions which had an aspect ratio of 4:3. Most modern monitors have an aspect ratio of 16:9. If you intend your game’s viewport to fill up the player’s monitor entirely, you will most likely want to match the aspect ratio of that monitor.
It may be more beneficial to choose a target display’s resolution and work backwards from there. By dividing a higher resolution evenly, your game will scale perfectly on that display.
According to the latest Steam Hardware Survey over 60% of Steam users are using a 1920 x 1080 monitor as their primary display. Laptops with a resolution of 1366 x 768 come in second at 10%.
You can simply divide the target resolution by a factor to find your working resolution. For example, 1920 x 1080 divided by 4 will result in a resolution of 480 x 270. A 1080p resolution divided by 5 will result in 384 x 216.
Godot Project Settings for Pixel Art
Once you have settled on a resolution, open up Godot’s project settings.
By default you will be on the "General" tab. On the left-hand side, will be all the categories. Scroll until you find Display > Window.
Set your chosen resolution. Then you can set the "test resolution" to be a multiple of that, so that your game window is a comfortable size when testing. You can even put the math right into the settings, and Godot will calculate it for you.
You will want to set the stretch mode to "Viewport". Furthermore you will want to set the stretch aspect to "Keep". You may have to scroll to see these settings. These settings ensures players using higher resolutions do not see more of the game. The edges of everyone’s view of the game are identical, even for people with ultrawide monitors.
You will also want to turn on "Pixel Snap". Both in the editor and the renderer. This will make it so that your computer isn’t trying to render half a pixel, and approximating the color to display. It will only display true pixels in your pixel art. And as of Godot 3.2.4 there is an additional option for snapping 2D transform to whole coordinates called "Use Transform Snap". In other words, when a pixel art object is moving it’s position will be rounded to the nearest whole pixel.
To set this in the Godot editor, close the project settings. Make sure you have the 2D viewport open. Click the three vertical dot icon and enable "Use Pixel Snap".
Any time you add a node of type "Sprite" or "AnimatedSprite", you will want to disable the "Centered" property. This is important for avoiding in-between pixel values when working with odd image sizes. When programming movement code, make sure all sprites are moved only in integer values.
In the FileSystem section, select your icon. Navigate to the "Import" tab. Select the "2D Pixel" option under "Preset". Click the "Reimport" button.
After that, open the "Preset" option again. Select "Set as Default for ‘Texture’". This will make it so that all image assets are imported using the "2D pixel" settings.
The Godot project settings are stored in the project.godot file. You can always just copy this file to a new project if you want to use these same pixel-perfect settings.
But what if you do want to support ultrawide monitors?
If you want to support mutiple aspect ratios, the Godot project setttings will almost have to be reversed. You will need to set your game’s resolution to the multiplied value. Scale your chosen resolution and use that as the project resolution. So with our example resolution of 384 x 216, multiplied by 4 gives us 1536 x 864. The test width and test height should be set to their default values of 0.
Still use the "Viewport" stretch mode. But set the stretch aspect to "keep_height" for a side-scrolling game. A vertical-scrolling game should use "keep_width".
Finally you will need to set the "Shrink" value to the scale factor you used for your resolution. In our example we would use 4 as the shrink value.