var canvas:BitmapData = new BitmapData(1000,1000,false, 0x000000);
addChild(new Bitmap(canvas));
scaleX = scaleY = .5;
var w:int = canvas.width;
var w10:int = w * 40;
var size:int = canvas.width * canvas.height;
for (var i:int = 0; i<size; i++){
var xp:int = i % w;
var yp:int = int(i / w);
var c1:int = (255/8) * (Math.cos(xp* Math.PI/180 * 2) + Math.sin(yp*(xp + 200)/w10));
if (c1 < 0) c1 = 256 - c1;
c1 = (c1 << 1 | c1) ;
canvas.setPixel(xp, yp, c1 <<15 | c1 <<7 | c1 );
}
var m:Matrix = new Matrix();
m.scale(1,-1);
m.translate(0,canvas.height);
var clone:BitmapData = canvas.clone();
canvas.draw(clone, m, null, BlendMode.SUBTRACT);
clone.draw(canvas);
clone.applyFilter(clone, clone.rect, new Point(0,0), new BlurFilter(10,10,1));
canvas.draw(clone, null, null, BlendMode.ADD);
Randomly bit shifting on this one is actually getting a good deal of millage.. I know I can easily optimize so that it works in realtime – could even be done in pixelbender… but going to play a bit more first before I optimize….
var canvas:BitmapData = new BitmapData(1000,1000,false, 0x000000);
addChild(new Bitmap(canvas));
scaleX = scaleY = .5;
var w:int = canvas.width;
var w10:int = w * 60;
var size:int = canvas.width * canvas.height;
for (var i:int = 0; i<size; i++){
var xp:int = i % w;
var yp:int = int(i / w);
var c1:int = (255/8) * (Math.cos(xp* Math.PI/180 * 2) + Math.sin(yp*yp/w10));
if (c1 < 0) c1 = 256 - c1;
c1 = (c1 << 1 | c1) ;
canvas.setPixel(xp, yp, c1 <<16 | c1 <<8 | c1 );
}
var m:Matrix = new Matrix();
m.scale(1,-1);
m.translate(0,canvas.height);
var clone:BitmapData = canvas.clone();
canvas.draw(clone, m, null, BlendMode.SUBTRACT);
clone.draw(canvas);
clone.applyFilter(clone, clone.rect, new Point(0,0), new BlurFilter(10,10,1));
canvas.draw(clone, null, null, BlendMode.ADD);
Having one of those days where everything I code doesn’t look right to me… took a little break from other work and created this very unoptimized abstract texture… no animation so here is a bitmap:
[SWF(width = 600, height=600, backgroundColor=0xCCCCCC, frameRate=24)]
var canvas:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight, false, 0x000000);
var blur:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight, false, 0x000000);
addChild(new Bitmap(canvas, "auto", true));
var w:int = canvas.width
var hw:int = w / 2;
var size:int = w * w;
var seed:Number = Math.random()*100;
var pnt:Point = new Point();
var dy:Number = 0, dx:Number = 0;
var blr:BlurFilter = new BlurFilter(10,10,1);
addEventListener(Event.ENTER_FRAME, onLoop);
function onLoop(evt:Event):void {
dx += (mouseX - dx) / 4;
dy += (mouseY - dy) / 4;
canvas.lock();
canvas.perlinNoise(hw,hw,2,seed,false, false, 1, true, [new Point(dx, dy), new Point(-dx, -dy)]);
var pix:Vector.<uint> = canvas.getVector(canvas.rect);
for (var i:int = 0; i<size; i++){
var col:uint = 255 - pix[i] << 4 & 0x00FF00;
pix[i] = col << 8 | col | col >> 8;
}
canvas.setVector(canvas.rect, pix);
blur.copyPixels(canvas, canvas.rect, pnt);
blur.applyFilter(blur, blur.rect, pnt, blr);
canvas.draw(blur, null, null, BlendMode.DIFFERENCE);
canvas.draw(canvas, null, null, BlendMode.INVERT);
canvas.unlock();
}
This is actually an optimized variation on some recent posts that made use of perlin noise. You can get a wide range of effects by changing just the BlendMode values alone…. I particularly like this combination of BlendModes because it reminds me a bit of a terrain map…
Have a look at the swf…
[SWF(width=500, height=500)]
var canvasSize:int=stage.stageWidth;
var canvas:BitmapData=new BitmapData(canvasSize,canvasSize,false,0x000001);
addChild(new Bitmap(canvas, "auto", true));
var size:int=canvas.width*canvas.height - canvasSize;
var pixels:Vector.<uint>=canvas.getVector(canvas.rect);
for (var i:int = 0; i<canvasSize; i++) {
var xp:int=int(Math.random()*canvasSize);
var yp:int=int(Math.random()*canvasSize);
pixels[xp+yp*canvasSize]=0xFF000000;
}
var targetCol:uint=0xFF000000;
var buffer:Vector.<uint>=pixels.concat();
var fade:uint=1;
addEventListener(Event.ENTER_FRAME, onLoop);
function onLoop(evt:Event):void {
var curr:uint=targetCol;
var r:int = (curr >> 16) & 0xFF;
var g:int = (curr >> 8) & 0xFF;
var b:int=curr&0xFF;
r+=fade;
g+=fade;
b+=fade;
if (r>255) r=255;
if (g>255) g=255;
if (b>255) b=255;
var darker:uint=0xFF000000|r<<16|g<<8|b;
if (darker==0xFFFFFFFF) {
removeEventListener(Event.ENTER_FRAME, onLoop);
}
for (var i:int = canvasSize; i<size; i++) {
curr=pixels[i];
if (curr==targetCol) {
var index:int=i-canvasSize+int(Math.random()*3) - 1;
if (index>0) buffer[index]=darker;
if (int(Math.random()*50)==1) {
index=i-canvasSize+int(Math.random()*3)-1;
if (index>0) buffer[index]=darker;
}
}
}
targetCol=darker;
canvas.lock();
canvas.setVector(canvas.rect, buffer);
pixels=buffer.concat();
canvas.unlock();
}
This snippet uses setVector() to draw something that looks like this:
This is a cellular automaton. It has kind of a strange rule set – but you could easily use this snippet to do more traditional cellular automata.
var canvasSize:int = 400;
var canvas:BitmapData = new BitmapData(canvasSize, canvasSize, false, 0xFFFFFF);
addChild(new Bitmap(canvas));
var size:int = canvas.width * canvas.height;
var pixels:Vector.<uint> = canvas.getVector(canvas.rect);
addEventListener(Event.ENTER_FRAME, onLoop);
function onLoop(evt:Event):void {
for (var i:int = 0; i<500; i++){
fillCircle(int(Math.random() * canvasSize),
int(Math.random() * canvasSize),
int(Math.random() * 5 + 3),
uint(Math.random() * 0xFFFF));
}
canvas.lock();
canvas.setVector(canvas.rect, pixels);
canvas.unlock();
}
function fillCircle(xp:int,yp:int, radius:int, col:uint = 0x000000):void {
var xoff:int =0;
var yoff:int = radius;
var balance:int = -radius;
while (xoff <= yoff) {
var p0:int = xp - xoff;
var p1:int = xp - yoff;
var w0:int = xoff + xoff;
var w1:int = yoff + yoff;
hLine(p0, yp + yoff, w0, col);
hLine(p0, yp - yoff, w0, col);
hLine(p1, yp + xoff, w1, col);
hLine(p1, yp - xoff, w1, col);
if ((balance += xoff++ + xoff)>= 0) {
balance-=--yoff+yoff;
}
}
}
function hLine(xp:int, yp:int, w:int, col:uint):void {
var index:int = xp + yp * canvasSize;
for (var i:int = 0; i <w; i++){
index++;
if (index > -1 && index < size){
pixels[index] = col;
}
}
}
In the past I’ve posted examples of Bresenham’s Circle (here and here). Both of those examples make use of setPixel(). Today’s snippet demos a version of Bresenham’s Circle that works with setVector().
var canvas:BitmapData=new BitmapData(400,400,false,0x000000);
addChild(new Bitmap(canvas));
var pix:Vector.<uint>=canvas.getVector(canvas.rect);
canvas.lock();
for (var i:int = 0; i<300; i++) {
var xp:int=50+i;
var yp:int=50+i/2;
// target x and y coords in 1D array
pix[xp+yp*400]=0xFFFFFF;
}
canvas.setVector(canvas.rect, pix);
canvas.unlock();
This snippet shows how to target x and y coordinates in a 1D Array / Vector. This can be useful sometimes when working with setVector().
This is sort of like re-inventing setPixel()…. and for that reason is kind of pointless – that said, it’s interesting to know. I first learned about this technique from using processing.
[SWF(width=600,height=500,frameRate=30)]
var canvas:BitmapData=new BitmapData(600,500,false,0x000000);
addChild(new Bitmap(canvas));
var size:Number=canvas.width*canvas.height;
var w:Number=canvas.width;
var wd:Number=1/w;
var pix:Vector.<uint> = new Vector.<uint>();
var sin:Number;
var cos:Number;
var dx:Number=110;
var dy:Number=52;
addEventListener(Event.ENTER_FRAME, onLoop);
function onLoop(evt:Event):void {
dx+=0.001;
canvas.lock();
for (var i:int = 0; i<size; i++) {
var xp:Number=i%w;
var yp:Number=int(i*wd);
var xx:Number=xp*0.05+dx;
var yy:Number=yp*0.05+dy;
var t:Number= (xx * yy) % 3.14159265;
//compute sine
// technique from http://lab.polygonal.de/2007/07/18/fast-and-accurate-sinecosine-approximation/
// by Michael Baczynski
if (t<0) {
sin=1.27323954*t+.405284735*t*t;
} else {
sin=1.27323954*t-0.405284735*t*t;
}
//compute cosine: sin(t + PI/2) = cos(t)
t+=1.57079632;
if (t>3.14159265) {
t-=6.28318531;
}
if (t<0) {
cos=1.27323954*t+0.405284735*t*t;
} else {
cos=1.27323954*t-0.405284735*t*t;
}
var c:Number=sin+cos*cos*cos;
// fast math abs
c=c<0? -c:c;
c=c*140;
// math max 255
c=c>255?255:c;
pix[i]=c<<16|c<<8|c;
}
canvas.setVector(canvas.rect, pix);
canvas.unlock();
}
The above snippet will animate a gradient that looks like this: