'Yellow Submarine' Effect and the Code

We show how to combine the BitmapData.perlinNoise method with the DisplacementMapFilter to create a psychedelic art effect. Combining the two techniques is common for creating a variety of effects. We explain the code and the details of Perlin noise and the DisplacementMapFilter.

Click the screen shot below or this link to open the effect in a new window:

Download

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

The Code

Here is the simple Timeline code behind the effect. We keep comments within the code for greater clarity.

/*
The warped, psychedelic image is our 'target image'. For instructional purposes we also display the undelying Perlin noise image and the image containing concentric circles before distortion.
*/

var targetWidth:Number=350;

var targetHeight:Number=300;

var targetData:BitmapData=new BitmapData(targetWidth,targetHeight,false,0xFF000000);

var targetBitmap:Bitmap=new Bitmap(targetData);

this.addChild(targetBitmap);

targetBitmap.x=175;

targetBitmap.y=30;

/*
In the Shape 'circles' we will draw clusters of concentric circles.
*/

var circles:Shape=new Shape();

/*
perlinData is a BitmapData object that will contain Perlin noise. New noise is generated at each click. perlinData will also serve as 'mapBitmap' for our instance of DisplacementMapFilter; that is, the source BitmapData for the filter. See the next page of the tutorial for details of Perlin noise and DisplacementMapFilter.
*/

var perlinData:BitmapData = new BitmapData(targetWidth,targetHeight, true, 0x00FFFFFF);

var seed:Number = Math.floor(Math.random() * 10000);

var channels:uint = BitmapDataChannel.BLUE;

var numOctaves:int=3;

perlinData.perlinNoise(100, 100, numOctaves, seed, false, false, channels, true, null);

/*
'perlinBitmap' and 'circlesBitmap' are displayed for instructional purposes only. They are not necessary to generate a psychedelic image.
*/

var perlinBitmap:Bitmap = new Bitmap(perlinData);

addChild(perlinBitmap);

perlinBitmap.x=30;

perlinBitmap.y=418;

perlinBitmap.scaleX=0.5;

perlinBitmap.scaleY=0.5;

var circlesBitmap:Bitmap=new Bitmap(targetData);

this.addChild(circlesBitmap);

circlesBitmap.x=500;

circlesBitmap.y=418;

circlesBitmap.scaleX=0.5;

circlesBitmap.scaleY=0.5;

/*
The drawAll function draws randomly generated circles and then uses the BitmapData.draw method to draw 'circles' into targetData.
*/

drawAll();

var dispFilter:DisplacementMapFilter=new DisplacementMapFilter();

dispFilter.mapBitmap=perlinData;

dispFilter.componentX=BitmapDataChannel.RED;

dispFilter.componentY=BitmapDataChannel.RED;

dispFilter.scaleX=50;

dispFilter.scaleY=50;

dispFilter.mode=DisplacementMapFilterMode.WRAP;

/*
We apply our DisplacementMapFilter to the Bitmap, targetBitmap. We could apply the filter to the BitmapData object, targetData, via applyFilter method. Notice though that we use targetData as BitmapData for two Bitmaps: targetBitmap and circlesBitmap. If we used targetData.applyFilter method both circlesBitmap and targetBitmap would be distorted.
*/

targetBitmap.filters=[dispFilter];

 

function drawAll():void {

circles.graphics.clear();

var cx:Number;

var cy:Number;

var j:int;

var i:int;

var numClusters:int=80;

var stripeWidth:Number=5;

var numCircles:int=10;

var radius:Number=numCircles*stripeWidth+stripeWidth;

for(j=0;j<numClusters;j++){

cx=Math.random()*targetWidth;

cy=Math.random()*targetHeight;

for(i=0;i<numCircles;i++){

circles.graphics.lineStyle(2,0x000000);

circles.graphics.beginFill(Math.random()*0xFFFFFF);

circles.graphics.drawCircle(cx,cy,radius-stripeWidth*i);

circles.graphics.endFill();

}

}

targetData.draw(circles);

}

 

btnNew.addEventListener(MouseEvent.CLICK,onClick);

 

function onClick(e:MouseEvent):void {

seed = Math.floor(Math.random() * 10000);

perlinData.perlinNoise(100, 100, numOctaves, seed, false, false, channels, true, null);

targetData=new BitmapData(targetWidth,targetHeight,false,0xFF000000);

targetBitmap.bitmapData=targetData;

circlesBitmap.bitmapData=targetData;

drawAll();

}

Note: A Perlin noise 'primitive', that is a BitmapData object filled with Perlin noise 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. You can find an example of a cloud effect obtained by combining Perlin noise and ColorMatrixFilter in our tutorial: Realistic White Clouds on Blue Sky in AS3 Flash, and a low CPU version of clouds in: AS3 Flash: Low CPU Clouds Animation - Perfect for Mobile.

On the next page we explain the details of Perlin Noise and the DisplacementMapFilter.

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.