By Zevan | January 19, 2009
Actionscript:
-
[SWF(width=500, height=500, backgroundColor=0xCCCCCC, frameRate=30)]
-
-
var canvas:BitmapData = new BitmapData(500, 500, true, 0xFF000000);
-
addChild(new Bitmap(canvas));
-
-
// create a radial gradient
-
var radial:Shape = new Shape();
-
var m:Matrix = new Matrix()
-
m.createGradientBox(500,500,0,0,0);
-
radial.graphics.beginGradientFill(GradientType.RADIAL, [0xFFFFFF, 0x000000], [1, 1], [0, 200], m, SpreadMethod.PAD);
-
-
radial.graphics.drawRect(0,0,500,500);
-
radial.x = radial.y = 0;
-
-
var displace:BitmapData = new BitmapData(500, 500, false,0xFF000000);
-
displace.perlinNoise(150,150, 3, 30, true, false,0,true);
-
-
// try different blendmodes here
-
displace.draw(radial, null ,null, BlendMode.LIGHTEN);
-
-
var displacementMap:DisplacementMapFilter = new DisplacementMapFilter(displace, new Point(0,0), 1, 1, 0, 0, DisplacementMapFilterMode.WRAP);
-
-
var scale:Number = 50 / stage.stageWidth;
-
-
addEventListener(Event.ENTER_FRAME, onLoop);
-
function onLoop(evt:Event):void {
-
-
canvas.copyPixels(displace, canvas.rect, new Point(0,0));
-
-
displacementMap.scaleX = 25 - mouseX * scale ;
-
displacementMap.scaleY = 25 - mouseY * scale ;
-
-
canvas.applyFilter(canvas, canvas.rect, new Point(0,0), displacementMap);
-
}
This one is hard to describe, so take a look at the swf first.
I think displacement maps are underused - they're very powerful. In this snippet I use a DisplacementMapFilter to create a parallax effect on some perlin noise and a radial gradient. The result is an abstract texture that looks 3D.
I got the idea from a demo for the alternative game engine. The first time I saw this demo I had no idea how they were doing it... but after looking at it a few times, I noticed some distortion around the neck area of the model... at that point I recognized it as a displacement map and whipped up a demo (using a drawings as the source image). The alternativa demo also has some color stuff happening to simulate lighting... I'm assuming that's done with a ColorMatrixFilter or two, but I'm not sure.
As in the alternativa demo, this technique could be used with 2 images... one depth map rendered out from your favorite 3D app and one textured render....
Also posted in 3D, misc | Tagged actionscript, flash |
By Zevan | January 16, 2009
Actionscript:
-
[SWF(width=500, height=500, backgroundColor=0x000000, frameRate=30)]
-
-
// draw an ugly gradient
-
var size:int = 500;
-
var pixNum:int = size * size;
-
var gradient:BitmapData = new BitmapData(size, size, true, 0xFF000000);
-
-
gradient.lock();
-
var xp:int, yp:int;
-
for (var i:int = 0; i<pixNum; i++){
-
xp = i % size;
-
yp = i / size;
-
gradient.setPixel(xp, yp, (yp /= 2) <<16 | (255 - yp) <<8 | (xp / 2) );
-
}
-
gradient.unlock();
-
-
// draw an alphaChannel (radial gradient)
-
var radius:Number = 50;
-
var diameter:Number = radius * 2;
-
-
pixNum = diameter * diameter;
-
-
var brushAlpha = new BitmapData(diameter, diameter, true, 0x00000000);
-
var dx:int, dy:int;
-
var ratio:Number = 255 / radius;
-
var a:int;
-
-
brushAlpha.lock();
-
for (i = 0; i<pixNum; i++){
-
xp = i % diameter;
-
yp = i / diameter;
-
dx = xp - radius;
-
dy = yp - radius;
-
a = int(255 - Math.min(255,Math.sqrt(dx * dx + dy * dy) * ratio));
-
brushAlpha.setPixel32(xp, yp, a <<24);
-
}
-
brushAlpha.unlock();
-
-
// create a black canvas
-
var canvas:BitmapData = new BitmapData(size, size, true, 0xFF000000);
-
addChild(new Bitmap(canvas));
-
-
addEventListener(Event.ENTER_FRAME, onLoop);
-
function onLoop(evt:Event):void {
-
// draw the gradient onto the canvas using the alphaChannel (brushAlpha);
-
xp = mouseX - radius;
-
yp = mouseY - radius;
-
canvas.copyPixels(gradient,
-
new Rectangle(xp, yp, diameter, diameter),
-
new Point(xp, yp), brushAlpha, new Point(0,0), true);
-
}
This demo creates an airbrush that paints one BitmapData onto another. This is achieved by using the alpha related arguments of the BitmapData.copyPixels() function. If your not familiar with these you should take some time to play around with them... they're very powerful.
copyPixels() is the fastest way to draw in flash, so if you need speed, copyPixels() is the way to go. It's much faster than using draw().
Also posted in setPixel | Tagged actionscript, flash |
By Zevan | January 15, 2009
Actionscript:
-
var size:Number = 400;
-
var pixelNum:Number = size * size;
-
var pixels:Vector.<uint> = new Vector.<uint>();
-
var r:uint;
-
var g:uint;
-
var b:uint;
-
-
var canvas:BitmapData = new BitmapData(size,size,false,0x000000);
-
addChild(new Bitmap(canvas));
-
-
addEventListener(Event.ENTER_FRAME, onLoop);
-
function onLoop(evt:Event):void {
-
-
canvas.lock();
-
-
// do any kind of pixel manipulation here:
-
-
for (var i:int = 0; i<pixelNum; i++) {
-
// draw a gradient that changes based on
-
// mouse position
-
r = i % size + mouseX;
-
b = i / size + mouseY;
-
g = (r + b) % mouseX;
-
pixels[i] = r <<16 | g <<8 | b;
-
}
-
canvas.setVector(canvas.rect, pixels);
-
//
-
-
canvas.unlock();
-
}
Using BitmapData.lock() and BitmapData.unlock() can speed up BitmaData drawing operations significantly. Simply lock your BitmapData before you draw to it, and unlock it when your done.
I often forget to do this until I get to the optimize phase of a project... but I think I'd like to get in the habit of doing it all the time....
By Zevan | January 14, 2009
Actionscript:
-
[SWF(width=400, height=400, backgroundColor=0xCCCCCC, frameRate=30)]
-
-
var canvas:BitmapData = new BitmapData(400, 400, true, 0xCCCCCC);
-
var eraser:BitmapData = new BitmapData(400, 400, true, 0x22CCCCCC);
-
addChild(new Bitmap(canvas));
-
-
var circle:Shape = Shape(addChild(new Shape()));
-
with (circle.graphics) beginFill(0x000000), drawCircle(0,0,20);
-
-
addEventListener(Event.ENTER_FRAME, onLoop);
-
-
function onLoop(evt:Event):void {
-
canvas.copyPixels(eraser, eraser.rect, new Point(0,0), null, null, true);
-
circle.x = mouseX;
-
circle.y = mouseY;
-
-
canvas.draw(circle, circle.transform.matrix);
-
}
Create trails by slowly erasing the background with copyPixels(). The first time I ever saw this technique was back when setpixel.com contained a bunch of great director experiments by Charles Foreman (creator of iminlikewithyou.com).
At some point last semester I showed iminlikewithyou hamster battle to my undergrad students towards the end of class.... probably one of the funniest moments of that class.
Also posted in misc | Tagged actionscript, flash |