Gaussian Blur Effect

Note: This is taken from the MetaVoxel development blog,

I started a task last week to add a simple Gaussian blur effect to the background blocks in the scene.  Before we were just drawing them with no filtering, so they looked “pixelated.” I tried using bilinear filtering, but that looks pretty ugly too. It ended up taking way too much time, but I learned a lot about image compositing and running convolution kernels on the GPU. Here are the results:

blur blur2

The algorithm splits the scene up into layers, similar to how you might do it in Photoshop. The “blur” layer is saved to a separate render target and filtered using a two-pass Gaussian blur. This makes for a nice softening effect. The layers are then composited together in a final merge step and rendered to the screen.

For those who care about the details, I ran into some issues with compositing, and it turned out that I’d been thinking about alpha blending all wrong. Most resources I’ve seen out there use linear interpolation for blending, based on the source alpha. The equation looks like:

dest = src_alpha * src_color+ (1 – src_alpha) * dst_color

In OpenGL, this is done through glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ).

There are some issues with this blend mode. For one, how do you represent complete transparency? Is it (0, 0, 0, 0)? Or (255, 255, 255, 0)? You can pick any arbitrary “color” for your transparent surface, which doesn’t really make physical sense. Even worse, if you render a texture into a transparent render target, you end up with discolored fringes:


The solution is to use premultiplied alpha. We instead use the blend mode:

dest = src_color + (1 – src_alpha) * dst_color

This way, (0, 0, 0, 0) is the only true transparent color. It reacts properly to filtering and avoids the ugly fringes. Once I switched the alpha blending to use premultiplied alpha, I was able to set the layer render targets to fully transparent, render into them, and then blend the layers together correctly.

This requires a bit of overhead for texture loading, because the input color is multiplied by the alpha channel. The results look very good though.



Since my last post, I started working on a new game project with a friend, Steven Barnett. It’s called MetaVoxel, and it’s a puzzle game involving a deeply recursive world.  What does that mean? Well, that’s a very good question. While initially tossing around ideas for the game, we decided it would be cool if the player could shrink to fit into a part of the world. In doing so, they would discover a deeper world within. The player can move in and out of these worlds to solve puzzles and discover new sub-worlds. Sure, it doesn’t make much sense, but who cares? We think it’s a cool idea. Here’s a concept painting by the illustrious and talented Steven:

At any rate, we’ve been hard at work on our new project, and we’re making a ton of progress. We’ve built a game editor for creating levels and crafting puzzles. We’re excited to show more, so in short order we’ll have a development blog online to show off our progress!