[Flash 11]

Decembre 2013

2D Lighting with ColorMatrixFilter


After reading this article on 2D lightning in game I have made a test with ColorMatrixFilter.


Full source code

package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.BlendMode;
	import flash.display.SimpleButton;
	import flash.display.Sprite;
	import flash.display.StageDisplayState;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.ColorMatrixFilter;
	import flash.filters.GlowFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.geom.Vector3D;
	
	/**
	 * ...
	 * @author YopSolo
	 */
	public class Main extends Sprite
	{
		[Embed(source="assets/diff.png")]
		private var DiffuseMapClass:Class;
		private var diffuseMap:Bitmap;
		[Embed(source="assets/norm.png")]
		private var NormalMapClass:Class;		
		[Embed(source = "assets/Gnome-View-Fullscreen-64.png")]
		private var FullScreeIconClass:Class;
		
		private var normalMap:Bitmap;
		private var result_dat:BitmapData;
		
		private var HALF_SCREEN:Rectangle;
		private var HALF_WIDTH:int;
		private var HALF_HEIGT:int;
		private var halfScreenFlag:Boolean;
		
		private var light:Vector3D;
		private var lighting:ColorMatrixFilter
		private var fullscreeIncon_btn:SimpleButton;
		
		public function Main():void
		{
			if (stage)
				init();
			else
				addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event = null):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			
			HALF_WIDTH = stage.stageWidth >> 1;
			HALF_HEIGT = stage.stageHeight >> 1;
			HALF_SCREEN = new Rectangle(HALF_WIDTH, 0, HALF_WIDTH, stage.stageHeight);
			
			halfScreenFlag = true;
			
			light = new Vector3D();
			lighting = new ColorMatrixFilter();
			
			// creating the map
			diffuseMap = new DiffuseMapClass();
			normalMap = new NormalMapClass();
			
			// on screen
			result_dat = diffuseMap.bitmapData.clone();
			addChild(new Bitmap(result_dat));
			
			// fullscreen button
			var img:Bitmap = new FullScreeIconClass();
			fullscreeIncon_btn = new SimpleButton(img, img, img, img);
			fullscreeIncon_btn.filters = [new GlowFilter(0xFFFF00,1, 10,10,3)];
			fullscreeIncon_btn.x = stage.stageWidth - img.width - 10;
			fullscreeIncon_btn.y = stage.stageHeight - img.height - 10;
			fullscreeIncon_btn.addEventListener(MouseEvent.CLICK, _onClickFullScreen );
			addChild( fullscreeIncon_btn );			
			
			//
			this.stage.addEventListener(MouseEvent.CLICK, _onClick);
			this.addEventListener(Event.ENTER_FRAME, _oef);
		}
		
		private function _onClickFullScreen(e:MouseEvent):void 
		{
			e.stopImmediatePropagation();			
			stage.fullScreenSourceRect = new Rectangle(0,0,1280,760);
			stage.displayState = StageDisplayState.FULL_SCREEN;
		}
		
		private function _onClick(e:MouseEvent):void
		{
			halfScreenFlag= !halfScreenFlag;
		}
		
		private function _oef(e:Event):void
		{
			light.x = -1 * ((HALF_WIDTH - mouseX) / stage.stageWidth);
			light.y = (HALF_HEIGT - mouseY) / stage.stageHeight;
			light.z = 1 - (light.x * light.x) - (light.y * light.y);			
			lighting.matrix = [2 * light.x, 2 * light.y, 2 * light.z, 0, (light.x + light.y + light.z) * -0xFF, 2 * light.x, 2 * light.y, 2 * light.z, 0, (light.x + light.y + light.z) * -0xFF, 2 * light.x, 2 * light.y, 2 * light.z, 0, (light.x + light.y + light.z) * -0xFF, 0, 0, 0, 1, 0];
			result_dat.fillRect(result_dat.rect, 0x0);
			result_dat.applyFilter(normalMap.bitmapData, normalMap.bitmapData.rect, normalMap.bitmapData.rect.topLeft, lighting);
			result_dat.draw(diffuseMap.bitmapData, null, null, BlendMode.MULTIPLY, halfScreenFlag ? HALF_SCREEN : null);
		}
	}
}

Vote in HexoSearch