[Flash 11]

Fevrier 2014

2D lighting with normal map, take 2

My first experiment with normal map and colorm matrix

Here another try, without ColorMatrixFilter (click on the swf then you can use space bar to remove the Color )


Assets used for this demo :

Another build of the previous scene using this technique
Click on the swf then you can use space bar to remove the Color and dbl click to go fullscreen.

Assets used for this demo :


package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.BlendMode;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageDisplayState;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	import flash.geom.Vector3D;
	import flash.ui.Keyboard;
	import flash.ui.Mouse;
	
	/**
	 * ...
	 * @author YopSolo
	 */
	public class Main extends Sprite
	{
		[Embed(source="assets/diff.png")]
		private const DiffuseClass:Class;
		[Embed(source = "assets/norm.png")]
		private const NormClass:Class;
		[Embed(source = "assets/lum.png")]
		private const LumClass:Class		
		
		private var normalMap:BitmapData;
		private var lightMap:BitmapData;
		private var dat:BitmapData;
		
		// ---------------------
		
		private const WIDTH:int = 1280;
		private const HEIGHT:int = 720;
		
		private var light:Vector3D;
		private var lightDst:int = 96;
		private var norm:Vector.;
		private var Nm:Vector3D = new Vector3D();
		private var Nl:Vector3D = new Vector3D();
		
		private const LIMIT:int = 128;
		private var power:int = 10000;
		private var diffuse:Bitmap;
		
		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);
			
			// config stage
			stage.align = StageAlign.TOP_LEFT;
			//stage.scaleMode = StageScaleMode.NO_SCALE;
			//stage.quality = StageQuality.LOW;
			stage.stageFocusRect = false;
			stage.tabChildren = false;
			
			light = new Vector3D(0, 0, lightDst);
			norm = new Vector.(WIDTH * HEIGHT, true); // wow such a big vector :D
			
			// diffuse
			diffuse = new DiffuseClass();
			addChild(diffuse);
			
			// normal map
			normalMap = (new NormClass() as Bitmap).bitmapData;
			
			// self light map
			lightMap = (new LumClass() as Bitmap).bitmapData;
			
			// my lightning
			dat = new BitmapData(normalMap.width, normalMap.height, false, 0x0);
			var bmp:Bitmap = new Bitmap(dat);
			bmp.blendMode = BlendMode.MULTIPLY;
			addChild(bmp);
			
			// filling my vector
			var xx:int = 0;
			var yy:int = 0;
			var coul:Number;
			var idx:int = 0;
			while (xx < WIDTH)
			{
				yy = 0;
				while (yy < HEIGHT)
				{
					coul = normalMap.getPixel(xx, yy);
					idx = (xx + (yy * WIDTH));
					norm[idx] = new Vector3D((-128 + ((coul >> 16) & 0xFF)), (-128 + ((coul >> 8) & 0xFF)), (-128 + (coul & 0xFF)));
					norm[idx].normalize();
					++yy;
				}
				;
				++xx;
			}
			
			Mouse.hide();
			
			stage.doubleClickEnabled = true;
			stage.addEventListener(MouseEvent.DOUBLE_CLICK, _onClickFullScreen);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, update);
			stage.addEventListener(KeyboardEvent.KEY_UP, _onSpaceBar);
		}
		
		private function _onSpaceBar(e:KeyboardEvent):void
		{
			if (e.keyCode == Keyboard.SPACE)
			{
				diffuse.visible = !diffuse.visible;
			}
		}
		
		private function _onClickFullScreen(e:MouseEvent):void
		{
			stage.fullScreenSourceRect = new Rectangle(0, 0, 1280, 760);
			stage.displayState = StageDisplayState.FULL_SCREEN;
		}
		
		private function update(e:MouseEvent):void
		{
			e.updateAfterEvent();
			e.stopImmediatePropagation();
			
			// --
			light.x = mouseX;
			light.y = mouseY;
			
			// --
			var xxMin:int = mouseX - LIMIT;
			if (xxMin < 0)
			{
				xxMin = 0;
			}
			var yyMin:int = 0;
			yyMin = mouseY - LIMIT;
			// --
			var xxMax:int = mouseX + LIMIT;
			if (xxMax > WIDTH)
			{
				xxMax = WIDTH;
			}
			var yyMax:int = mouseY + LIMIT;
			if (yyMax > HEIGHT)
			{
				yyMax = HEIGHT;
			}
			// --
			var len:Number;
			var c:uint;
			
			// --
			dat.fillRect(dat.rect, 0x444444);
Nl = new Vector3D();
			while (xxMin < xxMax)
			{
				yyMin = mouseY - LIMIT;
				if (yyMin < 0)
				{
					yyMin = 0;
				}
				while (yyMin < yyMax)
				{
					Nm = norm[(xxMin + (yyMin * WIDTH))];
					Nl.x = (xxMin - light.x);Nl.y = (yyMin - light.y);Nl.z = -(light.z);				len = Nl.length;
					Nl.normalize();
					c = ((power * (1 - Nm.dotProduct(Nl))) / len);
					if (c > 0xFF)
						c = 0xFF;
					dat.setPixel(xxMin, yyMin, (((c << 16) | (c << 8)) | c));
					++yyMin;
				}
				++xxMin;
			}
			
			// self illum
			dat.draw(lightMap, null, null, BlendMode.ADD);
		}
	
	}

}

Vote in HexoSearch