High quality blur filters can be expensive, so most bloom implementations do a cheap bilinear downsample to lower resolution before the ‘real’ blur. The original XNA sample operates at half resolution, but in a nod to the limited bandwidth of mobile GPUs, I made this version shrink to quarter size.

It is possible to implement Gaussian blur (or indeed any multi-tap filter) as a series of additive and subtractive blends with suitable offsets, but that gets expensive for large filter kernels. Instead I chose a Kawase blur (originally developed by Masaki Kawase for the Xbox1 game Wreckless), which cunningly exploits GPU bilinear filtering to get a not-quite-as-good-but-still-ok result more cheaply.

The threshold subtraction is perhaps the least intuitive operation. We want (source – threshold), but the alpha blending hardware only gives us (source – destination). So, we simply clear the destination rendertarget to our desired threshold value before drawing the source image!

There are two scaling operations in this bloom design: one to preserve full color range after the threshold subtraction, and a second after the blur to adjust intensity of the bloom. For efficiency, I apply these adjustments during the first and last blur passes, getting them for free as a side effect of drawing work that was already taking place.

I remembered seeing this post a while a back, and was curious to try it out now with some new projects. Shawn always provided great insight into the development and usage of XNA, which I'm sure many will sorely miss.

Of course with the recent release of Windows Phone 8, I'll still be using the 7.1 SDK as my preferred environment for night and weekend game development. You can have my XNA when you pry it from my cold, dead hands! 🙂