Postprocessing effects on WP7, Part II

For the first part of this mini-series, please read: Postprocessing effects on WP7, Part I

Starting from where we left of, this part will be focused on a single effect: random noise.

Random Noise

My original inspiration for this was the subtle ‘film grain’ effect seen in the first Mass Effect, though by no means do I think my version is anywhere near in quality and subtleness. Actually, I kinda pushed it to be more visible for the sake of this article.

The effect was simple enough to obtain, and with a bit of playing around with UV coordinates, it can be animated and looks decent.

The first thing I did was take a picture of static noise. These are easy enough to find or to produce. Here’s the one used in the sample.

As I write these words, I realize that there might be easier ways to get this on the screen, like drawing it with additive blending and a very low alpha. However, my wish was to add noise and ensure that the colors are not brightened too much.

I again took advantage of Color Blending, like in the last part, aiming for the following formula:

FinalColor = SourceColor - 0.15f * NoisePattern

By now it should be pretty easy to deduce that to achieve this, we can:

  • Set SourceBlend to Blend.One
  • Set DestinationBlend to BlendFactor, and set BlendFactor to (0.15f,  0.15f,  0.15f )
  • Set BlendFunction to Subtract
  • Draw the texture containing the noise pattern into the bakbuffer, so we can use it as the DestinationColor

Doing this leads to the following result.

Now remember you can play around with the BlendFactor and the 0.15 constant to achieve stronger or lighter noise, or to tint it. But it’s still static, and that’s not fun.

My initial instinct was to have a series of images, and in each frame, use another image as a noise patters, to make it look animated. But the beauty of an image filled with random static noise is that taking any part of it still results in an image of static noise.

So when drawing the noise pattern to the backbuffer, I simply select a rectangular area from inside the picture (always of the same size), and stretch that to fill the frame. Randomizing the position from where we take the image piece leads to seemingly animated noise.

public override Texture2D Apply(Texture2D input, GameTime gameTime)
{
    // Instead of using the whole noise image, we leave out a border of 100 pixels
    // This way, we can play with the position of the SourceRectangle to make the noise seem animated
    int pieceWidth = noiseTexture.Width-100;
    int pieceHeight = noiseTexture.Height-100;
    Rectangle sourceRect = new Rectangle(random.Next(100), random.Next(100), pieceWidth, pieceHeight);

    graphicsDevice.SetRenderTarget(buffer);
    graphicsDevice.Clear(Color.Black);
    spriteBatch.Begin(SpriteSortMode.Deferred, blendState);
    //Draw noise pattern, using the source rectangle
    spriteBatch.Draw(noiseTexture,new Rectangle(0,0,graphicsDevice.Viewport.Width,graphicsDevice.Viewport.Height),sourceRect, Color.White);
    //Draw input, which will subtract the noise pattern from the colors
    spriteBatch.Draw(input, Vector2.Zero, Color.White);
    spriteBatch.End();

    graphicsDevice.SetRenderTarget(null);
    return buffer;
}

The result, as an animated gif.

The code

You can download the code here: Part2.zip

Be sure to check back next time, when we’ll be looking at two more effects: radial blur and pixelated images.