topical media & game development
#filter-marble.ax
#filter-marble.ax
[swf]
flex
author: jmay
www.connectedpixel.com
All original source code listed here is licensed under a Creative Commons License.
package {
import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.geom.Matrix;
import flash.filters.BlurFilter;
import flash.filters.BitmapFilter;
import flash.filters.ColorMatrixFilter;
import flash.filters.DisplacementMapFilter;
import flash.geom.ColorTransform;
class @ax-filter-marble {
//////////////////////////////////////////////////////
// Properties. Settable via setter/getters below
// Sinusoidal or Perlin floor
private var _bSinusoidalFloor:Boolean = false;
// Sinusoidal floor parameters
private var _waveLength:Number = 100;
private var _sinMidColorPt:Number = 128;
private var _sinContrastMultiplier:Number = 1.0;
// Perlin floor parameters
private var _bPerlinFloorBaseX:Number = 50;
private var _bPerlinFloorBaseY:Number = 150;
private var _floorRandomSeed:Number = 317;
private var _perlinMidColorPt:Number = 128;
private var _perlinContrastMultiplier:Number = 2.0;
// Perlin floor modifiers
private var _contrastMultiplier:Number = 1.0;
private var _colorMidLevel:Number = 128; // offset
private var _veinAngleDeg:Number = 0;
// Marble Distortion parameters
private var _bEnableDistortion:Boolean = true;
private var _baseX :Number = 20;
private var _baseY :Number = 20;
private var _nOctaves :Number = 2;
private var _randomSeed :Number = 147;
private var _bFractalNoise :Boolean = false;
private var _blurX :Number = 5;
private var _blurY :Number = 5;
// Distortion strength
private var _displacementScaleX = 150;
// Color mapping
private var _rgb0:Number = 0x1c2a1f;
private var _rgb1:Number = 0xadc8b4;
//////////////////////////////////////////////////////
private var _identityMatrix:Matrix;
private var _identityColorTrans:ColorTransform;
private var _marbleColorFilter:ColorMatrixFilter;
private function invalidateMarbleColorFilter():void
{
delete _marbleColorFilter;
_marbleColorFilter = undefined;
}
////////////////////////////////////////////////////////////////
// Properties.
public function set sinusoidalFloor(bSin:Boolean):void { _bSinusoidalFloor = bSin; }
public function get sinusoidalFloor():Boolean { return _bSinusoidalFloor; }
public function set waveLength(len:Number):void {
if (isNaN(len)) return;
if (len < 2) len = 2;
if (len > 1000) len = 1000;
_waveLength = len;
}
public function get waveLength():Number { return _waveLength; }
public function set sinMidColorPt(val:Number):void {
if (isNaN(val)) return;
if (val < 10) val = 10;
if (val > 246) val = 246;
_sinMidColorPt = val;
}
public function get sinMidColorPt():Number { return _sinMidColorPt; }
public function set sinContrast(contrast:Number):void
{
if (contrast < 0.1 ) contrast = 0.1;
if (contrast > 10.0) contrast = 10.0;
_sinContrastMultiplier = contrast;
}
public function get sinContrast():Number { return _sinContrastMultiplier; }
/////////////////////////////////////////////////////////////////
public function set perlinMidColorPt(val:Number):void {
if (isNaN(val)) return;
if (val < 10) val = 10;
if (val > 246) val = 246;
_perlinMidColorPt = val;
}
public function get perlinMidColorPt():Number { return _perlinMidColorPt; }
public function set perlinContrast(contrast:Number):void
{
if (contrast < 0.1 ) contrast = 0.1;
if (contrast > 10.0) contrast = 10.0;
_perlinContrastMultiplier = contrast;
}
public function get perlinContrast():Number { return _perlinContrastMultiplier; }
public function set floorBaseX(bx:Number):void { _bPerlinFloorBaseX = bx; }
public function set floorBaseY(by:Number):void { _bPerlinFloorBaseY = by; }
public function get floorBaseX():Number { return _bPerlinFloorBaseX; }
public function get floorBaseY():Number { return _bPerlinFloorBaseY; }
public function set floorRandomSeed(seed:Number):void { _floorRandomSeed = seed; }
public function get floorRandomSeed():Number { return _floorRandomSeed; }
//////////////////////////////////////////////////////////////////////
public function set enableDistortion(bEnab:Boolean):void { _bEnableDistortion = bEnab; }
public function get enableDistortion():Boolean { return _bEnableDistortion; }
public function set perlinBaseX(bx:Number):void {
if (isNaN(bx)) return;
if (bx < 3) bx = 3;
if (bx > 1000) bx = 1000;
_baseX = bx;
}
public function get perlinBaseX():Number { return _baseX; }
public function set perlinBaseY(by:Number):void {
if (isNaN(by)) return;
if (by < 3) by = 3;
if (by > 1000) by = 1000;
_baseY = by;
}
public function get perlinBaseY():Number { return _baseY; }
public function set octaves(nOct:Number):void { _nOctaves = nOct; }
public function get octaves():Number { return _nOctaves; }
public function set rgb0(rgb:Number):void {
_rgb0 = rgb; invalidateMarbleColorFilter();
}
public function get rgb0():Number { return _rgb0; }
public function set rgb1(rgb:Number):void {
_rgb1 = rgb; invalidateMarbleColorFilter();
}
public function get rgb1():Number { return _rgb1; }
public function set seed(s:Number):void { _randomSeed = s; }
public function get seed():Number { return _randomSeed; }
public function set fractalNoise(bFractal:Boolean):void { _bFractalNoise = bFractal; }
public function get fractalNoise():Boolean { return _bFractalNoise; }
public function set displacementScaleX(dx:Number):void {
if (isNaN(dx)) return;
if (dx < 1) dx = 1;
if (dx > 256) dx = 256;
_displacementScaleX = dx;
}
public function get displacementScaleX():Number { return _displacementScaleX; }
//////////////////////////////////////////////////////////////////
public function @ax-filter-marble()
{
_identityMatrix = new Matrix();
_identityColorTrans = new ColorTransform();
}
//////////////////////////////////////////////////////////////////
// Convenience function. Returns a bitmap of the desired
// size using the current Marble settings.
/////////////////////////////////////////////////////////////////
public function createBitmap(w:Number,h:Number):BitmapData
{
var Marble_bmp:BitmapData = new BitmapData(w, h, false, 0x000000);
render(Marble_bmp);
return Marble_bmp;
}
///////////////////////////////////////////////////////////////////
// Render the Marble grain onto the bitmap using the current property
// values.
// buffer0_bmp and buffer1_bmp are optional. If they are not supplied
// temporary bitmaps will be created. They MUST have the same
// width and height as the destination bmp.
/////////////////////////////////////////////////////////////////
public function render(bmp:BitmapData):void
{
var w:Number = bmp.width;
var h:Number = bmp.height;
// Needed in some of the following flash api calls.
var rect:Rectangle = new Rectangle(0,0,w,h);
var origin:Point = new Point(0,0);
var mid:Number;
var mult:Number;
// The source bitmap needs to be larger than the destination bitmap because
// DisplacementMapFilter will grab pixels from a larger area.
var paddingX:Number = _displacementScaleX + 8; // Add 16 as slop
var floor_bmp:BitmapData = new BitmapData(w+paddingX,h,false,0x000000);
if (_bSinusoidalFloor){
drawSine(floor_bmp, _waveLength);
mid = _sinMidColorPt;
mult = _sinContrastMultiplier;
}
else{
floor_bmp.perlinNoise(_bPerlinFloorBaseX,_bPerlinFloorBaseY,1,_floorRandomSeed,false,true,4,false);
mult = _perlinContrastMultiplier;
mid = _perlinMidColorPt;
}
var offset:Number = mult * (mid-128);
var ampColor:Array = [1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, mult, 0, offset,
0, 0, 0, 1, 0 ];
var ampColorFilter:ColorMatrixFilter = new ColorMatrixFilter(ampColor);
floor_bmp.applyFilter(floor_bmp,floor_bmp.rectangle, origin, ampColorFilter);
///////////////////////////////////////////////////
// Add the marble distortion.
if (_bEnableDistortion){
// Will hold perlin noise.
var srcNoise_bmp:BitmapData = new BitmapData(w+paddingX, h, false, 0xffffffff);
// channelOptions - 4 - blue only
// grayscale - false
srcNoise_bmp.perlinNoise(_baseX,_baseY,_nOctaves,_randomSeed,false,_bFractalNoise,4,false);
var filter:DisplacementMapFilter = new DisplacementMapFilter(srcNoise_bmp,origin,4,1,_displacementScaleX,0);
var r:Rectangle = new Rectangle(paddingX/2,0,w,h);
bmp.applyFilter(floor_bmp,r,new Point(0,0),filter);
srcNoise_bmp.dispose();
}
else{
bmp.copyPixels(floor_bmp,rect,origin);
}
floor_bmp.dispose();
// Change it from black and blue to the desired colors.
bmp.applyFilter(bmp,rect, origin, getMarbleColorFilter());
}
private function drawSine(floor_bmp:BitmapData, wavelength:Number):void
{
var w:Number = floor_bmp.width;
// 1-pixel high bitmap.
var tmp_bmp:BitmapData = new BitmapData(w, 1);
var phaseInc:Number = 2 * Math.PI / wavelength;
var phase:Number = 0;
for (var x:Number = 0 ; x < w ; x++){
phase += phaseInc;
var colVal:Number = 127 * Math.cos(phase) + 128;
colVal = Math.round(colVal);
// We're dealing with blue only here.
tmp_bmp.setPixel(x,0,colVal);
}
var stretchMatrix:Matrix = new Matrix();
stretchMatrix.scale(1,floor_bmp.height);
// Now, draw the movieclip onto the floor_bmp
var blend:Object = 1; // normal
floor_bmp.draw(tmp_bmp,stretchMatrix,_identityColorTrans, blend);
// Clean up.
tmp_bmp.dispose();
}
/////////////////////////////////////////////////////////////////
// Map the black to blue colors to the desired Marble colors.
/////////////////////////////////////////////////////////////////
private function getMarbleColorFilter():ColorMatrixFilter
{
if (_marbleColorFilter != undefined){
return _marbleColorFilter;
}
// Apply the desired colors to the bitmap.
var r0:Number = (_rgb0 >> 16) & 0xff;
var g0:Number = (_rgb0 >> 8 ) & 0xff;
var b0:Number = _rgb0 & 0xff;
var r1:Number = (_rgb1 >> 16) & 0xff;
var g1:Number = (_rgb1 >> 8 ) & 0xff;
var b1:Number = _rgb1 & 0xff;
var marbleColor:Array = [0, 0, (r1-r0)/255, 0, r0,
0, 0, (g1-g0)/255, 0, g0,
0, 0, (b1-b0)/255, 0, b0,
0, 0, 0, 1, 0 ];
_marbleColorFilter= new ColorMatrixFilter(marbleColor);
return _marbleColorFilter;
}
}
}
(C) Æliens
27/08/2009
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.