Shield Cat's Rendering (Patreon)
Content
Hey guys! Figured I'd do something a little different today and talk about how Shield Cat gets graphics to the screen, so let's do it!
The Three Step Process
Shield Cat renders the game world to the screen in 3 phases:
- Game World Phase: This is when the game draws the stage, Lance, all enemies, gates, levers, and what have you. This is also when the game applies blur to the screen edges and whatnot (more on this later.)
- UI Phase: This is when the game draws things like Lance's health portrait, menus, dialogue boxes, and whatnot. First the game copies the drawing done by the Game World Phase to another texture, and then draws UI elements on top of it.
- Final Phase: This is when the game draws the final picture to the screen, applying any post processing effects.
Drawing the Game World

Here is a shot of the game view before the UI and post processing effects are added. Those of you who are familiar with the game will immediately note that this area is usually a lot more blue. It's not blue here because the color math hasn't been applied yet! I'll get into more detail in a bit.
Here's what happens during this time:
- Game Resolution: Before any drawing is done, the game determines what resolution it is to draw at. If "HiRes Mode" is enabled in the options, it will draw the game at the closest resolution to your monitor. For instance, if your screen is 1920x1080, the game will be drawn at 1920x1080. This allows sprites to have more precise movement across the screen, at the cost of not being pixel perfect. However, it gives an overall better presentation. If the option is disabled, the game is drawn at 640x360 and then upscaled later.
- Light Sources: If Lance is in a dark room with light sources all around, what the game does is disable writing any graphics data except the alpha channel and write in the specified opacity (for example, we'll say 50%.) This makes the game semitransparent, but doesn't change the color info. After that, the game draws all the light sources with additive blending, essentially making all the areas that are to appear lit up to be marked as opaque.
- Collectible Borders: During this time, the game will also re-draw the white borders on collectibles on top of everything else so that you can see them behind trees and whatnot.
All of this is rendered to a texture that has all the game world information as well as the transparency information used for the light sources, which I'll explain in a bit how it's done.
The UI Phase
Several things happen during the UI phase, so I'll break it down in the order it takes place.
Step 1: Copying the Game
To prepare copying the game, first another texture is created and filled with the color of my choosing. This background color will show through when we draw the game view to this new texture because of the transparency information we set while drawing light sources. It can be any color, allowing the lighting to not only be used for dark mysterious rooms, but also for snowy mountains and foggy places, simply by changing the background color to a bright color instead of a dark color.
A shader is applied when drawing the game view from earlier to this new texture. The following things are applied with this shader:
- Color Math: I can specify the color blending of the game view as well as the saturation of the image, allowing each area to have its own unique feel. This is the part that applies the blue colors to the image above. The background fill is also blue, which gives it its mysterious fog-like appearance. Transparency information isn't just for dark rooms! It can be used any time. I have an in-game editor which allows me to preview changes to this in real time.
- Camera Shake Offset: You've probably seen that the camera "shakes" but this is actually applied with a UV offset to the texture. What this means is that the camera never actually moves, and instead the game view is offset some when copying it. The outside area is simply stretched to fit, but you'd never notice it until I mention it in something like this. This prevents the camera from accidentally showing an out of bounds area, as well as prevents other issues from changing the position of the camera directly
- Blur: The shader applies blur effects to the game view. This blur is applied now so that the UI can be drawn on top of it, and is the main reason there's a 3 step process. Otherwise, the UI elements would be blurred as well! If there's no blur in the scene, the game switches to a shader that doesn't use blur. For efficiency, there's a separate shader for each level of blur, with hard coded values for each one.
- Dithering: The game applies a slight dithering to the image. This helps prevent color banding caused by displays simply being unable to display precise enough colors, especially in dark places. This also helps the bitcrush option to have its distinct look, as the dithering shines through and allows the game to appear to have more colors than it actually has during low color drawing.
- Distortion Mapping: This shader also applies any pulse effect you see on collectibles and other places in the game. This is sampled from another texture created while the game is drawing and then applied to the screen using fancy math.
Step 2: The Overlay

An overlay is drawn over the game world. It is essentially just a small part of a larger image that's stretched over the game view using interpolation. In the above picture you can see the color blending editor I use, where I've set the shadow opacity to 0. This allows the background color to completely shine through, and also allows you to see how the overlay is applied to the game view. I also have an in-game editor which allows me to draw directly on this image so I can see how it will be applied to the game world in real time. The combination of these two editors allows me to set up lighting for each room in a quick and efficient manner.
Step 3: Saving a Thumbnail
If you ever wondered how the game saves pictures of where you saved for when you next load the game, it is done now, after applying all of the color blending and whatnot, but before drawing the UI or adding any post processing effects.
Step 4: The UI
At this time, all of the UI elements are drawn. This includes the health, map, any menus, dialogue boxes, indicators, button prompts, and whatnot.
Step 5: Screen Transitions
After drawing everything else, if you're moving to another stage, the screen transition effect is drawn. Then, on top of this, other things are drawn such as stats for the new stage, or Lance's game over animation if you ran out of health.
All of this drawing is handled by a single object, which calls upon other objects to draw their things in a predictable order. It does NOT use Gamemaker's Draw GUI event, which will be explained in a moment here.
The Final Phase

In this phase, the second texture is actually drawn to the screen so you can see it. A shader is used to apply all of the post processing effects, such as the CRT shader you see above, scanlines, bitcrush (for the appearance of lower color depth) and what have you.
The CRT Blur filter actually has to apply all of these effects several time to each pixel to get it to work just right, which is about as slow as it sounds. That's why this shader can be so slow, especially if you're using it combined with the palette based shader! However, I'm always working on improving the efficiency of it, and in the next update I think you'll find that it works better than ever before because of significant improvements I made to it.
And there you have it! That's a summary of how Shield Cat gets graphics to the screen.
Graphics Options
If you've played Shield Cat, I'm sure you're aware of the tons of graphics options, so I wanted to explain some of them and how they work.
Upscaling
Since the game is a pixel art game, it has a fixed resolution of 640x360. It can also only draw to a fixed upscale of that, or the effects just don't work right. The upscaling mode determines how it handles it if your monitor is, say, 1680x1050. In this case, you have a few options available. The fast upscaling causes the game to draw at 1280x720, and then upscale that to fit your screen. It's very fast, but it's also a bit blurry. The high quality option, however, will draw the game at 1920x1080, and then downscale it to fit your screen. This produces a much clearer picture, but it also is slower on some devices. This is because some devices don't like drawing to a texture that's larger than the display resolution and then downscaling it. Most modern PCs don't have an issue with this, though.
Earlier I mentioned that if you have HiRes mode off, the game will draw at 360p. What happens in this situation is, the game will be drawn at 640x360, and then when it's copied it will be upscaled to either 1280x720 or 1920x1080, and then scaled again to fit your display.
Enhanced Mode
If you're thinking that all the drawing steps above sounds like it takes a lot of time, well, it does actually. Most modern computers don't have a problem with it, but some older or lower spec devices will. What the enhanced mode does is it cuts an entire step out of the drawing process. Instead of copying the game view to a second texture with a shader and then drawing UI elements on top of that, instead it just draws the game view, draws UI elements on it, and then draws that to the screen. This is why, when enhanced mode is off, all effects are disabled because the shaders are not being used and one less texture is being used as well. It doesn't look as pretty, but it's extremely fast, and is how I was able to get the game to run on raspberry pi.
The technical people reading this will wonder why I don't just draw directly to the back buffer. This is entire possible, but comes with a whole host of depth sorting issues and isn't really worth the trouble. There's an option in the configuration file called "DirectRender" that you can set to "true" which enables back buffer drawing, but you'll quickly see all the problems that come with it I think.
Conclusion
I hope that this writing has been informative and not too technical! It's something I've been wanting to write about for a while, but I never got around to it. If you have any questions or want me to explain something in more detail, please feel free to ask. Thank you!