I’m currently working on making images appear to “melt” for a website, but I’m hung up on a problem with displacement mapping.
The way my test works, I draw a path on a displacement map using the mouse, and this displacement is applied to the same image every frame (i.e., the displaced image of the last frame is displaced again). Colors are flowing along the path as they should, with one problem: the displaced pixels always turn transparent after a few seconds.
At first I thought this had something to do with the DisplacementMapFilterMode, so I tried setting it to “COLOR” using an opaque bright blue, while the stage behind my warped image is a highlighter green. Nope, the FilterMode color is only used for pixels sampled off the image, while my interior pixels were turning completely transparent instead of blue.
So, now I’m stumped. I’ve viewed my displacement map to make sure it looks right, I’ve tried setting the displacement scale to low and high numbers, and I’ve checked the channel assignments, all to no avail. Here’s my code, and I’ve attached the .fla as well. Any thoughts?
// "spider" is the name of a named movie clip instance containing
// an image on the stage, having the same dimensions as the stage
spider.visible = false;
var dispMap:BitmapData = new BitmapData(spider.width, spider.height, false, 0xff808000);
var gradient:Shape = new Shape();
var colors:Array = [0x800000, 0x808000];
var alphas:Array = [0xFF, 0xFF];
var ratios:Array = [0, 255];
// create blurred circle kernel used to draw on displacement map
var circ:Shape = new Shape();
var radius:Number = 20;
var initRadius:Number = 5;
// initialize to be transparent
circ.graphics.beginFill(0,0);
circ.graphics.drawRect(0,0,2*radius,2*radius);
circ.graphics.endFill();
// draw yellow (full x and y displacement) circle
circ.graphics.beginFill(0xFFFF00);
circ.graphics.drawCircle(radius, radius, initRadius);
circ.graphics.endFill();
// blur circle so center flows more quickly than edges
var blur:BlurFilter = new BlurFilter(8,8,3);
circ.filters = [blur];
//addChild(circ);
//circ.x = circ.y = 325;
// copy blurred circle to a bitmap for faster pasting later
var circbmp:BitmapData = new BitmapData(2*radius, 2*radius, true, 0);
circbmp.draw( circ );
//var circB:Bitmap = new Bitmap(circbmp);
//addChild(circB);
//circB.x = circB.y = 325;
// gradient used to create "drooping" effect - ignored for now
var transMat:Matrix = new Matrix();
transMat.createGradientBox( spider.width, spider.height + 40, Math.PI / 2 );
gradient.graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, transMat);
gradient.graphics.drawRect(0,0,spider.width, spider.height);
gradient.graphics.endFill();
//dispMap.draw(gradient);
// actual image being deformed
var spiderbmp:BitmapData = new BitmapData(spider.width, spider.height, true);
spiderbmp.draw(spider);
/* used to display the displacement map, which will be below the
deformed image by default*/
//var dispB:Bitmap = new Bitmap(dispMap);
//addChild(dispB);
// variables for adjusting the direction of displacement based on
// mouse motion
var lastPos:Point = new Point();
var currPos:Point = lastPos.clone();
var dx:Number, dy:Number, cosx:Number, sinx:Number, hyp:Number;
var sqrt:Function = Math.sqrt;
var colTrans:ColorTransform = new ColorTransform(1,1,1,1,0,0,0,0.5);
var mat:Matrix = new Matrix();
mat.identity();
var filt:DisplacementMapFilter = new DisplacementMapFilter( dispMap, new Point(), BitmapDataChannel.RED, BitmapDataChannel.GREEN, 20, 20, DisplacementMapFilterMode.COLOR, 0xff, 1);
// deformed image being displayed
var spi:Bitmap = new Bitmap(spiderbmp);
this.stage.addChild(spi);
this.stage.addEventListener(Event.ENTER_FRAME, update);
this.stage.addEventListener(MouseEvent.MOUSE_MOVE, moveKernel);
function update( e:Event )
{
// apply same displacement map to image every frame
spiderbmp.applyFilter( spiderbmp, spiderbmp.rect, new Point(), filt);
}
// adjust direction of flow for the mouse
function moveKernel( e:MouseEvent )
{
currPos.x = e.stageX;
currPos.y = e.stageY;
dx = currPos.x - lastPos.x;
dy = currPos.y - lastPos.y;
hyp = sqrt(dx * dx + dy * dy );
cosx = -dx / (hyp + .001);
sinx = -dy / (hyp + .001 );
lastPos.x = currPos.x;
lastPos.y = currPos.y;
colTrans.redMultiplier = cosx * 0.5 + 0.5;
colTrans.greenMultiplier = sinx * 0.5 + 0.5;
colTrans.alphaMultiplier = 1;
mat.tx = currPos.x - radius;
mat.ty = currPos.y - radius;
dispMap.draw(circbmp, mat, colTrans);
//map.copyPixels(newCirc, circbmp.rect, new Point());
}