This gnarly effect is sort of a semi-unintentional byproduct of my previous experiment.
Some of the same rules and techniques still apply: the main driving element is an animated perlinNoise map, but this time it’s used to supply pixel-displacement data.
Along with some basic sound-analysis and bitmapData effects it creates a pretty interesting end-result that in my mind is now officially stuck with the vaguely cyberpunk-inspired moniker “Aurora membrane”:
By the way, the suffocatingly sinister track is by Gök.
I have gone through at least a dozen different iterations of this effect, with various ways to filter, dampen, amplify or shuffle around the audiovisual data that drives the look, but ended up liking this unsettling, twitchy version the most.
Well, without further ado please feel free to dive right into the source.
Yes, that’s right: the source. Have fun kids, and stay in school!
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
// AURORA MEMBRANE (C) edvardtoth.com package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.BitmapDataChannel; import flash.display.PixelSnapping; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageQuality; import flash.display.StageScaleMode; import flash.events.Event; import flash.events.IOErrorEvent; import flash.filters.BlurFilter; import flash.filters.ColorMatrixFilter; import flash.geom.Point; import flash.geom.Rectangle; import flash.media.Sound; import flash.media.SoundChannel; import flash.net.URLRequest; import flash.utils.getTimer; [SWF(width=500,height=500,frameRate=30,backgroundColor=0x000000)] public class AuroraMembrane extends Sprite { private const SIZE:int = 500; // size of the canvas private const NOISESIZE:int = 100; // size of the noise map private const RATIO:Number = SIZE / NOISESIZE; // ratio to accurately map the noise on the canvas private const OCTAVES:int = 3; // number of perlin noise octaves private const SPEED:Number = 0.05; // speed value used to animate the perlin noise private var noiseMap:BitmapData; private var canvasBitmapData:BitmapData; private var canvas:Bitmap; private var canvasBlur:BlurFilter; private var canvasFade:ColorMatrixFilter; private var clipRect:Rectangle; private var point:Point; private var sound:Sound; private var channel:SoundChannel; private var leftMagnitude:Number; private var rightMagnitude:Number; private var soundAvailable:Boolean = true; public function AuroraMembrane() { // setup stage properties stage.scaleMode = StageScaleMode.NO_SCALE; stage.quality = StageQuality.MEDIUM; stage.align = StageAlign.TOP_LEFT; // create matrix for the ColorMatrixFilter used to fade out the continuously overdrawn bitmap var canvasFadeMatrix:Array = new Array(); canvasFadeMatrix = canvasFadeMatrix.concat([1, 0, 0, 0, 0]); // red canvasFadeMatrix = canvasFadeMatrix.concat([0, 1, 0, 0, 0]); // green canvasFadeMatrix = canvasFadeMatrix.concat([0, 0, 1, 0, 0]); // blue canvasFadeMatrix = canvasFadeMatrix.concat([0, 0, 0, 0.99, 0]); // alpha canvasFade = new ColorMatrixFilter (canvasFadeMatrix); canvasBlur = new BlurFilter (2, 32, 1); // Y values is much larger than X to achieve vertical streaking clipRect = new Rectangle (0, 0, SIZE, SIZE); point = new Point (0, 0); noiseMap = new BitmapData (NOISESIZE, NOISESIZE, false, 0x000000); canvasBitmapData = new BitmapData(SIZE, SIZE, false, 0x000000); canvas = new Bitmap(canvasBitmapData, PixelSnapping.AUTO, false); addChild(canvas); // load sound and handle potential stream error // effect should still be presentable even if sound cannot be loaded sound = new Sound(new URLRequest ("your soundfile location here")); sound.addEventListener(IOErrorEvent.IO_ERROR, function ():void{soundAvailable = false;}); channel = sound.play(); addEventListener (Event.ENTER_FRAME, updateFrame, false, 0, true); } private function updateFrame(event:Event):void { // get peak information from sound, or default to 1 if sound was not available to load if (soundAvailable == true) { leftMagnitude = channel.leftPeak; rightMagnitude = channel.rightPeak; } else { leftMagnitude = 1; rightMagnitude = 1; } var offsets:Array = []; var offset:Number = -(getTimer() * SPEED); for(var i:uint = 0; i < OCTAVES; i++) { // offsets are used for animating the various octaves of the perlin noise map offsets.push(new Point(0, offset/(i+1))); } // render the noiseMap noiseMap.perlinNoise(NOISESIZE, NOISESIZE, OCTAVES, Math.random(), false, false, BitmapDataChannel.RED |BitmapDataChannel.GREEN | BitmapDataChannel.BLUE , false, offsets); // apply fading and blurring to the existing contents of the canvas canvasBitmapData.applyFilter (canvasBitmapData, clipRect, point, canvasBlur); canvasBitmapData.applyFilter (canvasBitmapData, clipRect, point, canvasFade); for (var y:int = 0; y < NOISESIZE; y++) { for (var x:int = 0; x < NOISESIZE; x++) { // separate R,G,B values extracted from the noiseMap using bitwise operators var pixelColor:uint = noiseMap.getPixel(x, y); var r:int = pixelColor >> 16 & 0xFF; var g:int = pixelColor >> 8 & 0xFF; var b:int = pixelColor & 0xFF; // calculate coordinates for displaced pixels // the perlin noise map information drives the direction of the displacement, // and the sound values drive the magnitude var vX:int = x * RATIO + (g / 0xff - 0.25) * (leftMagnitude * SIZE); var vY:int = y * RATIO + (b / 0xff - 0.25) * (rightMagnitude * SIZE); // don't render out-of-bounds pixels if (vY < 0 || vY >= SIZE || vX < 0 || vX >= SIZE) { continue; } // render the displaced pixel with the right color value canvasBitmapData.setPixel(vX, vY, pixelColor); } } } } } |

fkin great stuff. the music kicks ass too
Really cool effect! Also awesame track!
Thx and keep it on.