Displacementmapfilter – Dynamischen Nebel erzeugen

Mai 20th, 2010 by admin

In diesem Displacementmapfilter Tutorial geht es um die Erzeugung von dynamischen Nebeleffekten. Hierzu erzeuge ich erst eine Nebelwand mittels einer Perlinschen Störung, in der ich zunächst die Dunklen bereiche transparent mache (je dunkler desto durchsichtiger) und anschließend deren Farbwerte durch Weiß ersetze. Das Ergebniss ist ein durchgehend weißes Bild, mit durchsichtigen Verläufen, wo sich zuvor dunkle Bereiche befanden.

FlashPlayer starten

Hier das Script:

 var fogData : BitmapData;
 var fog : Bitmap;
 var _w : int = 550;
 var _h : int = 400;
 
 var _perlinData : BitmapData ;
 var _dispFilter : DisplacementMapFilter ;
 
 var _perlinOff : Array = new Array;
 var _numOctaves : int = 3 ;
 
 var _baseX : int = 100 ;
 var _baseY : int = 100 ;
 var _strength : int = 50 ;
 
 
 createFogData() ;
 createFog() ;
 createDisplacement() ;
 addChild(fog);
 
 
 function createFogData() : void {
 
	fogData = new BitmapData( _w, _h ) ;
 	fogData.perlinNoise( _baseX, _baseY, _numOctaves, 10, true, true, 7, true, [new Point(0, 0) ] ) ;	
 }
 
 function createFog() : void {
 
	var rect : Rectangle = new Rectangle( 0, 0, _w, _h ) ;
	var old_bytes : ByteArray = fogData.getPixels( rect ) ;
	var new_bytes : ByteArray = new ByteArray();
 
	old_bytes.position = 0 ;
 
	for (var i:int = 0; i < old_bytes.length; i+=4) 
	{				
		new_bytes[i + 0] = 255 - old_bytes[i + 1] ; // alpha is negated R (R == G == B)
 
		new_bytes[i + 1] = 255 ; 
		new_bytes[i + 2] = 255 ;
		new_bytes[i + 3] = 255 ; // RGB = 0xffffff
	}
 
	fogData.setPixels( rect, new_bytes ) ;
	fog = new Bitmap( fogData ) ;
	fog.alpha = .5;
}
 
 function createDisplacement() : void {
 
		_perlinOff = new Array ;
		_perlinOff.push( new Point ) ;
		_perlinData = new BitmapData( _w , _h, false ) ;
		_dispFilter = new DisplacementMapFilter( _perlinData, new Point( ), BitmapDataChannel.RED, BitmapDataChannel.GREEN, _strength, _strength, "color" ) ;
 
		this.addEventListener( Event.ENTER_FRAME, perlinize );
}
 
 function perlinize( e:Event ) : void {
			_perlinOff[0].x++;
			_perlinOff[0].y++;
			_perlinData.perlinNoise( _baseX, _baseY, 1, 50, true, true, 7, false, _perlinOff ) ;
			fog.filters = [ _dispFilter ] ;
		}

Das Ganze funktioniert folgdender Maßen: Man lädt die Pixelwerte des Perlin-Bildes in ein Bytearray. Hier stehen immer vier bytes (8 Bits, also werte zwischen 0 und 255) für einen Kanal, ALPHA – RED – GREEN – BLUE, in dieser Reihenfolge. Da in der perlin() funktion der parameter Grayscale aktiviert ist, entsprechen die bytes 2-4 einander (R = G = B), somit ist jeder Pixel grau, weil kein Farbkanal den anderen überwiegt.
Ersetzt man nun das erste Byte ALPHA mit 255 (nicht transparent) durch 255 – R (je dunkler desto durchsichtiger), muss man nur noch die Übrigen bytes R G und B auf 255 (ergibt weiß) setzen und schon hat man die besagte Nebelwand.

Anschließend wird eine weitere, diesmal in einer ENTER_FRAME Schleife fortlaufend gemachte Perlinsche Störung in Kombination mit einem Displacementmapfilter dazu benutzt, der Nebelwand eine realistische, dynamische Bewegung zu geben.

Das Ergebniss ist schaurig schön, nicht wahr?