Faking Depth of Field in Papervision 3D

A while back I was given my first flash project that required me to use Papervision 3D. If that wasn’t daunting enough, the design of the project required that there be a depth of field effect on the elements – something that papervision cannot do. (If i am wrong about that, please don’t tell me now…)

After learning the basics of papervision – which has plenty of tutorials on the interwebs – I started brainstorming an approach for faking depth of field. Here is what I came up with.

Simplifying the concept, I basically just needed to ‘blur’ the objects as they moved close to or far away from the camera. I couldn’t blur the object itself, but I could change the textures on the fly, so that became the basis of my approach.

I couldn’t just blur the textures on the objects because the edges would not look right. The blur needed to extend past the edge of the objects. My solution for this was to set up extra 3d planes for each of the objects that needed blur. As the objects moved, their distance from the camera was tested. If they were outside the threshold area, the blurred plane object was substituted in, and the blurry textures were swapped around based on the particular distance.

It seemed to work pretty well. Here is a slightly simplified version of the concept, using just the planes. As you move the mouse around, you will see the planes appear to blur – this is the textures swapping

Show Depth of Field demo

Now for the funky bit. Because there were a bunch of different textures I needed to work with, I didn’t want to have to created every level of blur for every image. It would be burden on my time and increase download times.

What I ended up doing was created a method that took in one texture and generated all of the blurs for me. Each of the different blurs was then stored in an array so that I could easily switch between them.

This is the code that I used, but looking at it now I could have done it a bit better dropping out the ‘draw()’ method and applying the blur to the BitmapData directly.

	 * Generates an array of bitmap data objects ranging from no blur to the blur amount
	 * @param	origBitmapData	- the original bitmap to blur
	 * @param	blurAmount		- the maximum amount of blur to create
	 * @param	steps			- the number of various blur amounts to generate
	 * @return  An array of BitmapData objects
	public function generateBlurredBitmapArray(origBitmapData:BitmapData, blurAmount:Number = 40, steps:Number=8):Array {
		// set up a return array to hold the data
		var returnArray:Array = [];
		// create the blur filter
		var blur:BlurFilter = new BlurFilter(0,0,2);
		// generate a sprite to apply the blur to
		var s:Sprite = new Sprite();
		// create a bitmap to hold the original bitmap data - add it to the sprite
		var b:Bitmap = new Bitmap(origBitmapData, "auto", true);
		// position it in the centre
		b.x = b.y = blurAmount;
		// loop through and generate the required number of blurs
		for (var i:uint = 0; i < steps; i++) {
			// adjust the blur and apply it to the sprite
			blur.blurX = blur.blurY = blurAmount * (i / (steps - 1))
			s.filters = [blur];
			// generate the new bitmap data
			var newBmpData:BitmapData = new BitmapData(origBitmapData.width + (blurAmount * 2), origBitmapData.height + (blurAmount * 2), true, 0x00ffffff);
			// draw the sprite to it
			newBmpData.draw(s, null, null, null, null, true);
			// add this to the return array
		// return the array
		return returnArray;

That’s about it. Hope that helps you out – let me know what you think!

Leave a Reply

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

Name *

This site uses Akismet to reduce spam. Learn how your comment data is processed.