In photography, the depth of field refers to the area in front of the camera that appears sharp and in focus. This effect is quite often used to emphasize a portion of a scene, while de-emphasizing the foreground and background.
When rendering a scene in Away3D, there is no depth of field; the entire scene is in perfect focus. However, the effect can be approximated by using the DepthOfFieldSprite
class, which will precalculate a number of increasingly blurry images from the material that is supplied to the DepthOfFieldSprite
constructor and store them in a shared cache. One of these images will then be displayed by the sprite at runtime depending on the distance of the DepthOfFieldSprite
object to the camera.
package { import away3d.containers.ObjectContainer3D; import away3d.core.base.Mesh; import away3d.core.utils.Cast; import away3d.core.utils.DofCache; import away3d.materials.BitmapMaterial; import away3d.sprites.DepthOfFieldSprite; import flash.display.BitmapData; import flash.events.Event; public class DepthOfFieldSpriteDemo extends Away3DTemplate {
We embed an image file, which will be used as the base texture for the DepthOfFieldSprite
objects.
[Embed(source="blackdot.png")] protected var BlackDot:Class;
The container Mesh
into which we will be adding the DepthOfFieldSprite
objects is referenced by the container
property.
protected var container:Mesh; public function DepthOfFieldSpriteDemo () { super(); }
The DofCache
class includes a number of properties that define the appearance of the DepthOfFieldSprite
class. These have been defined in the initEngine()
function.
protected override function initEngine():void { super.initEngine();
The aperture
property is used to approximate the effect of a camera's aperture. Larger values for the aperture
property increase the depth of field, meaning that DepthOfFieldSprite
objects remain relatively sharp over a large area in front of the camera. Smaller values will lead to DepthOfFieldSprite
objects appearing sharp within a smaller area.
DofCache.aperture = 50;
The doflevels
property defines how many discreet levels of blurriness will be precalculated and cached for a given bitmap image. One of these cached images will then be displayed by a DepthOfFieldSprite
object at runtime, depending on its position relative to the camera. Larger values for the doflevels
property result in a smoother transition from one cached image to the next. However, this increased visual quality requires more memory to accommodate the additional cached images and takes more time while the images are precalculated.
DofCache.doflevels = 32;
The maxblur
property defines the maximum blurriness to apply to a DepthOfFieldSprite
object. Larger values for the maxblur
property will result in more pronounced distinction between those DepthOfFieldSprite
objects that are in the depth of field and those that are not.
DofCache.maxblur = 50;
The focus
property defines the distance in front of the camera where DepthOfFieldSprite
objects are considered to be in focus.
DofCache.focus = 2000;
Setting the usedof
property to true
will allow DepthOfFieldSprite
objects to display the depth of field effect. Otherwise, they would behave like a regular Sprite3D
object.
DofCache.usedof = true; }
Each of the properties defined in the DofCache
class, with the exception of usedof
, has an equivalent property in the Camera3D
class. The enableDof()
function from the Camera3D
class copies these properties from the Camera3D
class to the DofCache
class, and sets the usedof
property to true
.
The reason why we have set the values directly on the DofCache
class, instead of using those in the Camera3D
class, is because the camera's focus will quite often be different to the value used to calculate the depth of field effect. If you remember from Chapter 7, Cameras, setting the camera's focus to 2,000 would decrease the camera's field of view, which would have the undesired effect of providing a very narrow view of the scene.
To get the effect we are after, the values that affect the depth of field effect are set directly on the DofCache
class, and the camera is left alone.
In the initScene()
function, we create a number of DepthOfFieldSprite
objects and add them to the scene.
protected override function initScene():void { super.initScene();
Here we define a reference to a BitmapMaterial
object that will be supplied to the DepthOfFieldSprite
constructor.
It would be possible to create the DepthOfFieldSprite
objects with their own reference to a BitmapMaterial
object with the following code:
var sprite: DepthOfFieldSprite = new DepthOfFieldSprite( new BitmapMaterial(Cast.bitmap(BlackDot)) ) );
However, doing so increases the amount of time it takes to initialize the application. Supplying a common material object to the DepthOfFieldSprite
constructor avoids this issue.
var blackDotBitmap:BitmapMaterial = new BitmapMaterial(Cast.bitmap(BlackDot));
The container Mesh
that will hold the DepthOfFieldSprite
objects is created, positioned, and added to the scene.
container = new Mesh({z: 1000}); scene.addChild(container);
Now we create the DepthOfFieldSprite
objects, and randomly place them in a 1,000 x 1,000 x 1,000 unit area. Because the DepthOfFieldSprite
objects are children of the Mesh
object created above, their global range along the Z-axis will be from 500 to 1,500, while their ranges on the X and Y axes will both be from -500 to 500.
var sprite:DepthOfFieldSprite; for (var i:int = 0; i < 250; ++i) { sprite = new DepthOfFieldSprite(blackDotBitmap); sprite.x = Math.random() * 1000 - 500; sprite.y = Math.random() * 1000 - 500; sprite.z = Math.random() * 1000 - 500 container.addSprite(sprite); }
In the onEnterFrame()
function, the container is rotated around the Y-axis. This, in turn, rotates the children DepthOfFieldSprite
objects, modifying their distance to the camera, and thus showing off the depth of field effect.
protected override function onEnterFrame(event:Event):void { super.onEnterFrame(event); container.rotationY += 1; } } }
As you can see from the following screenshot, those DepthOfFieldSprite
objects that lay within the depth of field are drawn as sharp black dots. As the DepthOfFieldSprite
objects move progressively further outside the depth of field, they become increasingly blurred.