tech

smooth plasma experiment

While playing with Alchemy, I focused a lot on C and C++ CG resources (like this great one).
Like many coders, I’ve always been fascinated by old school demoscene effects. ^^

Inspiration finally came, and I had good time producing some little experiments to play with.
Here’s one of them that I’m glad to share with you.
That’s two animated plasmas mixed together using same color palette. Color palette is splitted in 3 collections, one for red channel, another for green. Blue is unused. The last one is for handling pixels transparency.




Some optimizations tricks deployed to get display smoothness:
- Plasmas are mixed together without blending. I’m drawing one pixel of each (with boolean checker) while generation.
- I use ByteArray (as video ram like low-level languages do) with BitmapData.setPixels for rendering. I discover it’s faster to not compute each channel if you don’t need it.
- As often, few as3 optimizations tips (Vector collections, int indexes, binary shifting for arithmetical operations, while loop without coordinates…)

Here’s the source code. Enjoy !

package  
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageQuality;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.filters.BlurFilter;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.ByteArray;		
 
	[SWF( width="400", height="400", frameRate="25" , backgroundColor="0x000000")]	
	public class Plasma 
		extends Sprite 
	{
		protected const w : int = 400;
		protected const h : int = 400;
 
		protected var bd : BitmapData;
		protected var ba : ByteArray;
		protected var position : uint;
		protected var p : Point;
		protected var rect : Rectangle;
		protected var shifter : int;
		protected var blur : BlurFilter;
 
		protected const A : Vector.<int> = new Vector.<int>( 256, true );
		protected const R : Vector.<int> = new Vector.<int>( 256, true );
		protected const G : Vector.<int> = new Vector.<int>( 256, true );
		protected var plasma : Vector.<int>;
 
		public function Plasma()
		{
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			stage.quality = StageQuality.LOW;
 
			ba = new ByteArray();
			p = new Point(0, 0);
			rect = new Rectangle( 0, 0, w, h );
			bd = new BitmapData( w, h, true, 0 );
			blur = new BlurFilter( 4, 4, 1 );
			addChild( new Bitmap( bd ) );
 
			// generate palette
			var i : int = 256;
			while( --i > - 1 )
    		{
    			A[i] = int(128 + 128 * Math.sin( 3.1415 * i / 32));
        		R[i] = int(128 + 128 * Math.sin( 3.1415 * i / 16));
        		G[i] = int(128 + 128 * Math.sin( 3.1415 * i / 64));
    		}
 
    		// generate plasma
    		var x : int, y : int, l : int = w*h, b : Boolean = true;
    		plasma = new Vector.<int>( l, false );
 
			while(  --l > - 1 )
			{
  				x = l % w;
				y = (l - x) / w;
				var color : Number;
 
				if ( b )
					color = (128+(128*Math.sin(x/128))+128
					+(128*Math.sin(y/128)))/2;
				else
					color = (128+(128*Math.sin(x/16))+128
					+(128*Math.sin(y/8))+128
					+(128*Math.sin((x+y)/16))+128
					+(128*Math.sin(Math.sqrt(x*x+y*y)/8)))/4;
 
        		plasma[l] = color;
        		b = !b;
    		}
 
			// init screen
			for( x = 0; x < w; x++ )
			{
				for( y = 0; y < h; y++ )
				{
					var pos : Number = (x+(y*w))*4;
					ba[pos] = 255;
					ba[pos+1] = 0;
					ba[pos+2] = 0;
					ba[pos+3] = 0;
				}
			}
 
			addEventListener( Event.ENTER_FRAME, enterFrame );
		}
 
		protected function enterFrame( e : Event ) : void
		{
			bd.lock();
			var t : int = ++shifter, pos : int = w*h, palID : int, ID : int;
			while ( --pos > - 1 )
			{
					palID = int((plasma[pos] + t) % 255);
					// to process ARGB channels, same as pos *= 4;
					ID = int(pos << 2); 
					ba[ID]	= A[palID];
					ba[ID+1]= R[palID];
					ba[ID+2]= G[palID];
        	}
			ba.position = 0;
			bd.setPixels( rect, ba );
			bd.applyFilter( bd, bd.rect, p, blur );
			bd.unlock();
		}
	}
}

Share on Twitter

Discussion

5 comments for “smooth plasma experiment”

  1. ça y est Francis devient demomaker ! (un peu tard mais bon…)

    Posted by antoNo Gravatar | décembre 22, 2008, 21:58
  2. [...] Pour tester l’engin je me suis monté une page en quelques clicks et j’ai inséré le code du plasma que je vous avais proposé dans un précédent billet. [...]

    Posted by actionscript online avec wonderfl | tweenpix | décembre 31, 2008, 15:32
  3. [...] school fire effect By Francis Bourre ⋅ 4 janvier 2009 ⋅ Post a comment After the plasma experiment, I feel motivated to play again with pixels and old school demoscene effects. I continued to [...]

    Posted by old school fire effect | tweenpix | janvier 4, 2009, 18:33
  4. J’ai adapté ce code pour faire un plug-in pour Onyx-VJ, est-ce que je peux le publier sur mon blog avec le code source?
    Thanks for sharing!

    Posted by BatchassNo Gravatar | janvier 23, 2009, 7:39
  5. @Batchass Pas de souci ! Enjoy ! ;)

    Posted by Francis BourreNo Gravatar | janvier 23, 2009, 8:56

Post a comment

-->

Recent Comments

  • Viagra ordre
  • Cialis en ligne
  • Levitra en ligne
  • Propecia acheter
  • Viagra acheter
  • Acheter cialis
  • Ordre levitra
  • Ordre propecia
  • En ligne viagra
  • Vente cialis
  • Levitra bon marche
  • Propecia en ligne
  • Viagra online
  • Buy cialis
  • Order Levitra
  • Buy propecia
  • Buy viagra
  • Cheap cialis
  • Cheap Levitra
  • propecia online
  • Viagra prescription
  • Cialis online
  • Buy Levitra
  • Order propecia