Header image

ND2D – Blur

December 7th, 2011 | Posted by lars in Molehill / Stage3D | ND2D | Pixelshader

Good news everyone. I found a little time to implement a blur shader for ND2D and I’m trying to explain how to implement a shader like this:

First of all: How does a blur work? To blur an image, you sample neighbouring pixels of each pixel in the image and compute the average color. For example if you have a 3×3 image and the pixel in the middle is black, the rest white. You sample all neighbours of the middle pixel (r: 1.0 g: 1.0 b: 1.0) * 8 plus the pixel itself (r: 0,0 g: 0,0 b: 0,0) * 1 and compute the average (divide by 9), the resulting pixel will be (r: 0,88 g: 0,88 b: 0,88). Just do that for every pixel in the image and you’ll have a blur.

To implement this in a shader we have to consider a few things: First you want to save as many texture sampling calls as possible. For example if you want to blur your image 4 pixels horizontally and vertically, you would have to take 9 x 9 = 81 samples (4 to the left, up and down and the pixel that should be blurred itself). This is way too much and you could never squeeze this into a fragment shader with AGAL. But there is a trick: First blur your image horizontally, take the result and blur it vertically. This way, you have to take only 9 + 9 = 18 samples (see Article: Gaussian Blur Shader). Implementing it this way, means we have to do a horizontal blur, write the output to a texture and do a vertical blur with the already horizontal blurred texture. In other words, a two pass rendering. A nice sideeffect of this approach is, that we can not only blur in x AND y direction, but in x OR y individually.

So we’ve implemented our blur now and are happy that everything is blurry with a 4×4 blur, but how do we animate it now? We could generate the shader dynamically, so that we would have a different shader for different blur values, but space is limited in a fragment shader. A program can’t exceed a certain size. What if we want to have a blur of 50 x 50? We can’t write a shader that does this. The program would be just too big, since we don’t have loops in AGAL.

One part of the answer is good old: Carl Friedrich Gauß. He invented a formular a few hundred years ago, that let’s us weighten the sampled pixels (see Article: Guassian Blur and an Implementation). So our shader can remain static and sample always 9 pixels, but the gaussian function will tell us how the samples are treated. So instead of dividing all samples by 9, we have a factor for each sample. Now not only the blur is dynamic, it even looks a lot better with the gauss values than our simple “divide by 9″ approach. Neat! Now we can animate a blur from 0 to 4 pixels. That’s ok, but we wanted 50 or more, remember?

The last and final part to our full dynamic blur shader is: Just repeat what we’ve done already! If you want to have a blur of 10, just blur two times by 4 pixels, followed by a 2 pixel blur. Implementing this is also straight forward: setRenderToTexture(), renderBlur(), switchTextures(). All done in a loop.

Enough of the tech talk, here’s the result (move your mouse to blur the sprites in x and/or y):

You’ll notice the ugly edges in the middle image. This happens, if the blur is larger than the transparent space available in the texture. So the blur is “cut off”. I haven’t found a good solution for this, except of: Leave enough space in your textures if you want to blur it ;)

You can follow any responses to this entry through the RSS 2.0 You can leave a response, or trackback.

8 Responses

  • mi77jp says:

    Thank You!
    I tried other all, ND2 is the best molehilling framework, for pure action script coders like me.

  • Nice blur shader! I had a question regarding how you implement those shaders in ND2D. I’ve used some on standard Flash DisplayObjects before, but never in Molehill. What are the steps to use a Pixelbender shader on a Stage3D object? Can it be applied to the entire screen as well as individual objects?

    Thanks for sharing this awesome library :)

  • lars says:

    @chamberlainpi: You can’t use the 2D Pixelbender with Stage3D. This would be only possible with the Pixelbender 3D, but I can’t recomment this one, because it’s unfinished an buggy. So you have to code shaders in AGAL and you can do whatever you can think of with them ;)

  • @lars: Ok I should clarify my question. I just want to understand the whole process of post processing in Stage3D. Do you have to: Render your scene, draw it to a BitmapData, create a new Scene with only one screen Quad (plane object) with your original Scene as the texture, then use a Fragment Shader to blur the scene? Or…
    Applying a PixelBender2D Shader to the rendered Scene (as BitmapData) then draw it to the screen Quad?

    I’m not sure I understand how you can sample pixels around one given pixel location (unless I’m not thinking “outside the box” enough!)

  • lars says:

    To achieve a blur, you could render your whole scene (or parts of the scene) to a native Context3D texture and render a full screen quad with this texture and a blur fragment shader. BitmapData and PixelBender2D is a totally different world and don’t exist in a Stage3D environment.

  • @lars: Oh nice! I didn’t realize there was a method ‘setRenderToTexture(…)’, I’ll keep that in mind :) Thanks a lot!

  • Hey! I love this shader code! Thanks a lot for sharing it.

    The only problem is that it blends the colour of neighbouring pixels that have an alpha of zero.

    So if you blur a texture that is simply a white circle surrounded by transparent pixels it will gain a black outline.

    Any plans on updating the shader to change this?

    Anyway, love the shader, thanks again.

  • Pingback: NORTHWAY Games » Blog Archive » An Ink-Bleed Fade



Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">