[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); } } }