Advanced 2D Shaders in MonoGame
A tutorial series on creating advanced 2D visual effects with custom shaders in MonoGame.
This tutorial series picks up where the Building 2D Games tutorial left off, diving deep into the world of custom shaders. The goal is to develop tooling for MonoGame to facilitate shader development, write some custom effects for DungeonSlime, and build intuition for how to approach shader programming.
What We Will Build
Throughout this series, we will take our Dungeon Slime game and add a whole new layer of visual polish. By the end, you will have implemented a variety of advanced shader effects, including:
- A scene transition effect,
- A color swap effect,
- A 3d effect using
SpriteBatch, - A lighting system using techniques from deferred rendering,
- A shadow system using stencil buffers.
Who This Is For
This documentation is for intermediate MonoGame users. It assumes that you have a solid understanding of C# and have already completed the entire "Building 2D Games" tutorial series.
Important
The concepts and code from the original tutorial, especially the Shaders chapter, are a mandatory prerequisite. We will be building directly on top of the final project from that series.
Table of Contents
This documentation is organized to be read sequentially, as each chapter builds upon the techniques and code from the previous one.
| Chapter | Summary | Source Files |
|---|---|---|
| Chapter 01: Introduction | An overview of the advanced shader techniques covered in this tutorial series. | Final Chapter from Building-2D-Games Series |
| Chapter 02: Hot Reload | Set up a workflow with a "hot-reload" system to recompile and view shader changes in real-time without restarting the game. | 02-Hot-Reload |
| Chapter 03: The Material Class | Create a Material class to manage shader parameters and handle the complexities of the shader compiler and our hot-reload system. |
03-Material-Class |
| Chapter 04: Debug UI | Integrate ImGui.NET to build a real-time debug UI, allowing for runtime manipulation of shader parameters. | 04-Debug-UI |
| Chapter 05: Transition Effect | Create a flexible, texture-driven screen wipe for smooth scene transitions. | 05-Transition-Effect |
| Chapter 06: Color Swap Effect | Implement a powerful color-swapping system using a 1D texture as a Look-Up Table (LUT), allowing for dynamic color palette changes. | 06-Color-Swap-Effect |
| Chapter 07: Sprite Vertex Effect | Dive into the vertex shader to manipulate sprite geometry, break out of the 2D plane, and give the game a dynamic 3D perspective. | 07-Sprite-Vertex-Effect |
| Chapter 08: Light Effect | Build a 2D dynamic lighting system from scratch using a deferred rendering approach, complete with color, light, and normal map buffers. | 08-Light-Effect |
| Chapter 09: Shadows Effect | Add dynamic 2D shadows to the lighting system by using a vertex shader and the stencil buffer for efficient light masking. | 09-Shadows-Effect |
| Chapter 10: Conclusion & Next Steps | Review the techniques learned throughout the series and preview further graphics programming topics to continue your journey. |
Conventions Used in This Documentation
The following conventions are used in this documentation.
Italics
Italics are used for emphasis and technical terms.
Highlights
Highlights are used for paths such as file paths, including filenames, extensions and other critical information in the application of steps in a tutorial. These are similar to Inline code blocks as they stand out more in Markdown and require emphasis.
Inline Code Blocks
Inline code blocks are used for methods, functions, and variable names when they are discussed within the paragraphs of text. For example, when referring to a method such as Foo in a sentence, it will appear with this formatting.
Code Blocks
// Example Code Block
public void Foo() { }
Code blocks are used to show code examples with syntax highlighting. These appear as separated blocks rather than inline with text, allowing for multi-line examples and better readability of complete code snippets.
MonoGame
If you ever have questions about MonoGame or would like to talk with other developers to share ideas or just hang out with us, you can find us in the various MonoGame communities below:
Note From Author
My name is Chris Hanna (notably, I am not Christopher Whitley, who wrote the wonderful Building 2D Games series). I have very fond memories of using MonoGame back in 2010 (when it was called XNA) to put code I wrote (!) onto my humble Xbox 360. My young mind was delighted. I have been a life long lover of game development. Before XNA, I learned to program by using Dark Basic Pro. Then XNA taught me how to use "real" languages like C#. Learning C# eventually led me to the Unity game engine, which helped me find a job in the gaming industry in 2019 at a game studio called Disruptor Beam (which has become a new company called Beamable). I owe a lot to tools like MonoGame, and the communities that build and maintain them.
I drifted away from MonoGame around 2018, finding myself using tools like Unity instead. Then, I found my way back to MonoGame after the Unity Runtime Fee debacle of 2023. Like many game developers, I wanted to find a game framework that I could trust and rely on. MonoGame was the top of my list. I was even able to contribute to MonoGame, by helping upgrade the texture compression tools from legacy XNA-era tools to modern standards.
I had always wanted to learn computer graphics and shaders, but for years, I had never been able to build the fundamental intuition. I remember trying to learn shaders at the same time I was learning C#, back in the 2010-era, and I could not make heads or tails of it all. I tried to learn shaders again a few years later and still struggled to really grasp the foundations of what a shader is. To be honest, I owe my current understanding of shaders to tools like Shader Toy, and specifically, the youtube channel, The Art Of Code. The way the author, Martijn, explained the basic concepts of shader mathematics was exactly what my brain needed to see. All of his tutorials started with a tiny template shader, and through many (many) small incremental updates, he would always arrive at a shader that produced beautiful imagery on the screen. Procedural generation shaders are one of my favorite things. There is truly something magical about seeing complex visuals produced by the construction of simple arithmetics. My knowledge of shaders ballooned after that.
I hear a lot of people say, "shaders are magic". They are magical, but we are the wizards! The truly magical thing about shaders is that you can wield their power to create wonderful things. I hope that this shader tutorial will help you connect some of the basic intuitions in your brain, and that you come to enjoy shader programming as much as I do.
Acknowledgements
This documentation would not have been possible without the support and contributions from numerous individuals within the MonoGame community.
I would like to acknowledge that this tutorial series would not be possible without the help and guidance of many people. The entire MonoGame foundation deserves endless credit for keeping MonoGame active and relevant, and specifically, Simon Jackson needs immense gratitude for editing and reviewing this tutorial. I also think that Christopher Whitley merits on-going applause for creating the original tutorial content. Lastly, MonoGame exists because there is a strong community of developers who love using MonoGame.