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