Comments on Perlin Noise and DisplacementMapFilter

DisplacementMapFilter

An instance of the DisplacementMapFilter can be applied to a DisplayObject via the DisplayObject.filters property. It can also be applied directly to a BitmapData object by BitmapData.applyFilter. The latter technique permanently alters the BitmapData object which may not always be desirable.

The DisplacementMapFilter displaces the pixels of a target object to which the filter is applied based on color values of a source BitmapData called 'mapBitmap'. The displacement creates warping effects.

The properties of an instance of the DisplacementMapFilter can be set in its constructor (or afterwards as in our code). The constructor takes the following (optional) parameters:

var dispFilter:DiaplacementMapFilter = new DisplacementMapFilter(mapBitmap:BitmapData = null, mapPoint:Point = null, componentX:uint = 0, componentY:uint = 0, scaleX:Number = 0.0, scaleY:Number = 0.0, mode:String = "wrap", color:uint = 0, alpha:Number = 0.0)

The values of these parameters may be set afterwards through, for example:

dispFilter.scaleX=50;

The meaning of the parameters is as follows.

  • mapBitmap - A BitmapData object whose pixel information is used to calculate displacements in the target image.
  • mapPoint - the offset of the upper-left corner of the target display object from the upper-left corner of the map image. Usually (0,0).
  • componentX - Describes which color channel to use in the map image to displace the x result. Possible values are the BitmapDataChannel constants, e.g. dispFilter.componentX = BitmapDataChannel.RED;
  • componentY - Describes which color channel to use in the map image to displace the y result. Possible values are the BitmapDataChannel constants, e.g. dispFilter.componentY = BitmapDataChannel.RED;
  • scaleX - The multiplier to use to scale the x displacement result from the map calculation.
  • scaleY - The multiplier to use to scale the y displacement result from the map calculation.
  • mode - The mode of the filter. Possible values are the DisplacementMapFilterMode constants:
    DisplacementMapFilterMode.WRAP
    DisplacementMapFilterMode.CLAMP
    DisplacementMapFilterMode.IGNORE
    DisplacementMapFilterMode.COLOR

    The modes determine what happens to the pixels for which displacement calulations fall out of range. 'WRAP', for example, wraps and brings pixels from the other side; 'CLAMP' repeats pixels at the edge etc.

The last two parameters matter only if the mode is 'color'. In that case the pixels for which displacement calulations fall out of range are substituted by a fixed color with fixed alpha given by the parameters.

It is worth mentioning how the displacement of the pixels in the image to which the filter is applied is calculated based on the parameters. Assume that mapPoint.x=mapPoint.y=0; that is, offsets are 0. Let dstPixel[x,y] denote the pixel in the image at (x,y) after the filter is applied, srcPixel[w,v] the pixel at (w,v) in the image before the filter is applied. Here is the formula for displacement:

dstPixel[x, y] = srcPixel[x + ((componentX(x, y) - 128) * scaleX) / 256, y + ((componentY(x, y) - 128) *scaleY) / 256)]

Which pixel in the image will be moved by the filter to the position (x,y)? According to the formula, it will be the pixel originally at the position: x + ((componentX(x, y) - 128) * scaleX) / 256, y + ((componentY(x, y) - 128) *scaleY) / 256).

componentX(x,y) and componentY(x,y) are the selected color channel values of pixels in mapBitmap at (x,y). Those values are between 0 and 255. Assume scaleX and scaleY are positive. In that case, if the pixel in the mapBitmap at (x,y) is brighter than medium (128), the pixel that will move to (x,y) after the filter is applied is originally to the right and down from (x,y). If componentX(x,y), componentY(x,y) are less than 128, the pixel that moves to (x,y) is originally to the left and up of (x,y) etc. (If mapPoint is not (0,0), componentX(x,y) and componentY(x,y) are calculated with offsets.)

The meaning of the parameters is discovered best by experimenting. You can use sub.fla in the zip package for experimenting.

AS3 BitmapData.perlinNoise Method

Perlin noise is based on a complicated algorithm that creates random-looking textures. The algorithm is purely deterministic; that is, the same parameters will produce identical results. Yet, because of its clever construction, the results will appear random. If you'd like to hear about the algorithm and its many uses from the author himself, you can find here Professor Ken Perlin's lecture.

In AS3, you can create BitamapData objects in which color channel values are governed by a Perlin noise with parameters of your choice. Such a BitmapData 'primitive' filled with Perlin noise can then be used to create a large variety of image effects. Perlin noise 'primitive' is rarely used on its own. Most of the time it is combined with an instance of the DisplacementMapFilter, as in our example, or an instance of the ColorMatrixFilter as in the tutorial: Realistic White Clouds on Blue Sky in AS3 Flash.

The method takes the following parameters:

perlinNoise(baseX:Number,baseY:Number,numOctaves:uint,randomSeed:int,
          stitch:Boolean,fractalNoise:Boolean,channelOptions:uint=7,
          grayScale:Boolean=false,offests:Array=null):void

  • baseX is reponsible for horizontal 'frequency' of the noise. The lower the value of baseX, the higher horizontal frequency. With low baseX, you will see plenty of small clouds spread horizontally.
  • baseY is reponsible for vertical 'frequency' of the noise. The lower the value of baseY, the higher vertical frequency.
  • numOctaves is crucial and it is most responsible (together with the size of the image) for the CPU usage during your effect. Each next 'octave' is a separate layer of the noise. It has twice the frequecy of the prevoius octave and adds detail to the effect. We use numOctaves=3. You should choose settings appropriate to the nature and size of your image or animation. Each octave significantly adds to the CPU usage and can slow down animation.
  • randomSeed the starting point for the algorithm. We choose it randomly each time the user clicks the New Image button.
  • stitch smoothes the edges of the image to make tiling of Perlin noise easier.
  • fractalNoise setting it to true or false dramatically alters the nature of the noise. Try experimenting by changing the code in sub.fla.
  • channelOptions specifies to which color channels the noise is applied. It may be passed as integer: 1 for red channnel only, 3 for red and green, 7 for red, green and blue, 15 red, gree, blue and alpha. It is much easier to specify the channelOptions parameter using bitwise OR. For example, pass as channelOptions
    BitmapDataChannel.RED
    for red,
    BitmapDataChannel.RED | BitmapDataChannel.GREEN | BitmapDataChannel.BLUE
    for red, green and blue etc. In our case, channels do not matter much as we use grayscale noise.
  • grayScale set to true produces a grayscale noise, false gives multicolored noise.
  • offsets is an Array of Points. Each element of the Array corresponds to one octave and gives horizontal and vertical offset for that octave. In our example, the parameter remains constant.

To really learn the meaning of all the parameters, you have to experiment with them. You can use sub.fla for experimentation.

Download

Download the well-commented source files corresponding to the effect above:

Back to Intermediate              Back to Flash and Math Home

We welcome your comments, suggestions, and contributions. Click the Contact Us link below and email one of us.

Adobe®, Flash®, ActionScript®, Flex® are registered trademarks of Adobe Systems Incorporated.