Toggle navigation
Sign Up
Log In
Explore
Works
Folders
Tools
Collections
Artists
Groups
Groups
Topics
Tasks
Tasks
Jobs
Teams
Jobs
Recommendation
More Effects...
ActionScript
// forked from yonatan's CMLMovieClipTexture package { import flash.display.*; import flash.events.*; import flash.filters.*; import flash.geom.*; import flash.net.*; import flash.system.*; [SWF(width="465", height="465", frameRate="24", backgroundColor="0xc0c0c0")] public class FlashTest extends Sprite { private var horses:Array = []; private var frameCnt:int = 0; public static const FOCUS:Number = 300; public static const MAX_Z:Number = 4000; public static const MIN_Z:Number = 20; public static const NUM_HORSES:int = 40; private var occ:Sprite = new Sprite; private var vol:VolumetricPointLight; public function FlashTest() { var url:String = "http://assets.wonderfl.net/images/related_images/d/d5/d5ef/d5efb19c4e6af524be0c935a932a653b475d2200"; var loader:Loader = new Loader; loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoad); loader.load(new URLRequest(url), new LoaderContext(true)); } private function onLoad(e:Event):void { var bmd:BitmapData = Bitmap(e.target.content).bitmapData; var vmargin:int = 10; var hmargin:int = 40; var w:int = bmd.width / 4 - hmargin*2; var h:int = bmd.height / 3 - vmargin*2; var rect:Rectangle = new Rectangle(0, 0, w, h); var frame:BitmapData; for(var y:int=0; y<3; y++) { for(var x:int=0; x<4; x++) { frame = new BitmapData(w, h, true, 0); rect.x = x*bmd.width/4+hmargin; rect.y = y*bmd.height/3+vmargin; frame.copyPixels(bmd, rect, frame.rect.topLeft); Horse.animation.push(frame); } } Horse.animation.pop(); // lose last frame for each(frame in Horse.animation) createAlpha(frame); for(var i:int=0; i
> 8) & 0xff)) + Math.abs(0xb0 - ((c >> 16) & 0xff))); match /= (3*0xb0); match += 0.3; match = Math.min(1, Math.pow(match, 5)); bmd.setPixel32(x, y, c | ((match*0xff) << 24)); } } } private var bmp:Bitmap = new Bitmap; private function onEnterFrame(e:Event):void { for each(var horse:Horse in horses) horse.update(); } } } import flash.display.*; class Horse extends Bitmap { public static var animation:Array = []; public var frame:int; public function update():void { bitmapData = animation[frame>>1]; x += 0.5*(width * (0.15 + (0.6+0.4*Math.cos(frame/22*Math.PI+1.6))*0.1)); if(x > 465) x = -465 - width; if(++frame == 22) frame = 0; } } import flash.display.*; import flash.events.*; import flash.filters.*; import flash.geom.*; /** * The EffectContainer class creates a volumetric light effect (also known as crepuscular or "god" rays). * This is done in 2D with some bitmap processing of an emission object, and optionally an occlusion object. */ class EffectContainer extends Sprite { /** * When true a blur filter is applied to the final effect bitmap (can help when colorIntegrity == true). */ public var blur:Boolean = false; /** * Selects rendering method; when set to true colors won't be distorted and performance will be * a little worse. Also, this might make the final output appear grainier. */ public var colorIntegrity:Boolean = false; /** * Light intensity. */ public var intensity:Number = 4; /** * Number of passes applied to buffer. Lower numbers mean lower quality but better performance, * anything above 8 is probably overkill. */ public var passes:uint = 6; /** * Set this to one of the StageQuality constants to use this quality level when drawing bitmaps, or to * null to use the current stage quality. Mileage may vary on different platforms and player versions. * I think it should only be used when stage.quality is LOW (set this to BEST to get reasonable results). */ public var rasterQuality:String = null; /** * Final scale of emission. Should always be more than 1. */ public var scale:Number = 2; /** * Smooth scaling of the effect's final output bitmap. */ public var smoothing:Boolean = true; /** * Light source x. * @default viewport center (set in constructor). */ public var srcX:Number; /** * Light source y. * @default viewport center (set in constructor). */ public var srcY:Number; protected var _blurFilter:BlurFilter = new BlurFilter(2, 2); protected var _emission:DisplayObject; protected var _occlusion:DisplayObject; protected var _ct:ColorTransform = new ColorTransform; protected var _halve:ColorTransform = new ColorTransform(0.5, 0.5, 0.5); protected var _occlusionLoResBmd:BitmapData; protected var _occlusionLoResBmp:Bitmap; protected var _baseBmd:BitmapData; protected var _bufferBmd:BitmapData; protected var _lightBmp:Bitmap = new Bitmap; protected var _bufferSize:uint = 0x8000; protected var _bufferWidth:uint; protected var _bufferHeight:uint; protected var _viewportWidth:uint; protected var _viewportHeight:uint; protected var _mtx:Matrix = new Matrix; /** * Creates a new effect container. * * @param width Viewport width in pixels. * @param height Viewport height in pixels. * @param emission A DisplayObject to which the effect will be applied. This object will be * added as a child of the container. When applying the effect the object's filters and color * transform are ignored, if you want to use filters or a color transform put your content in * another object and addChild it to this one instead. * @param occlusion An optional occlusion object, handled the same way as the emission object. */ public function EffectContainer(width:uint, height:uint, emission:DisplayObject, occlusion:DisplayObject = null) { if(!emission) throw(new Error("emission DisplayObject must not be null.")); addChild(_emission = emission); if(occlusion) addChild(_occlusion = occlusion); setViewportSize(width, height); _lightBmp.blendMode = BlendMode.ADD; addChild(_lightBmp); srcX = width / 2; srcY = height / 2; } /** * Sets the container's size. This method recreates internal buffers (slow), do not call this on * every frame. * * @param width Viewport width in pixels * @param height Viewport height in pixels */ public function setViewportSize(width:uint, height:uint):void { _viewportWidth = width; _viewportHeight = height; scrollRect = new Rectangle(0, 0, width, height); _updateBuffers(); } /** * Sets the approximate size (in pixels) of the effect's internal buffers. Smaller number means lower * quality and better performance. This method recreates internal buffers (slow), do not call this on * every frame. * * @param size Buffer size in pixels */ public function setBufferSize(size:uint):void { _bufferSize = size; _updateBuffers(); } protected function _updateBuffers():void { var aspect:Number = _viewportWidth / _viewportHeight; _bufferHeight = Math.max(1, Math.sqrt(_bufferSize / aspect)); _bufferWidth = Math.max(1, _bufferHeight * aspect); dispose(); _baseBmd = new BitmapData(_bufferWidth, _bufferHeight, false, 0); _bufferBmd = new BitmapData(_bufferWidth, _bufferHeight, false, 0); _occlusionLoResBmd = new BitmapData(_bufferWidth, _bufferHeight, true, 0); _occlusionLoResBmp = new Bitmap(_occlusionLoResBmd); } /** * Render a single frame. * * @param e In case you want to make this an event listener. */ public function render(e:Event = null):void { if(!(_lightBmp.visible = intensity > 0)) return; var savedQuality:String = stage.quality; if(rasterQuality) stage.quality = rasterQuality; var mul:Number = colorIntegrity ? intensity : intensity/(1<
This should also perform a little better than EffectContainer. */ class VolumetricPointLight extends EffectContainer { protected var _colors:Array; protected var _alphas:Array; protected var _ratios:Array; protected var _gradient:Shape = new Shape; protected var _gradientMtx:Matrix = new Matrix; protected var _gradientBmp:Bitmap = new Bitmap; protected var _lastSrcX:Number; protected var _lastSrcY:Number; protected var _lastIntensity:Number; protected var _lastColorIntegrity:Boolean = false; protected var _gradientLoResBmd:BitmapData; protected var _gradientLoResDirty:Boolean = true; /** * Creates a new effect container, with an emission created from the supplied color or gradient. * The constructor lets you use a shortcut syntax for creating simple single-color gradients. * @example The shortcut syntax: *
new VolumetricPointLight(800, 600, occlusion, 0xc08040);
* @example is equivalent to: *
new VolumetricPointLight(800, 600, occlusion, [0xc08040, 0], [1, 1], [0, 255]);
* * @param width Viewport width in pixels. * @param height Viewport height in pixels. * @param occlusion An occlusion object, will be overlayed above the lighting gradient and under the light effect bitmap. * @param colorOrGradient Either a gradient colors array, or a uint color value. * @param alphas Will only be used if colorOrGradient is an array. This will be passed to beginGradientFill. * If not provided alphas will all be 1. * @param ratios Will only be used if colorOrGradient is an array. This will be passed to * beginGradientFill. If colorOrGradient is an Array and ratios aren't provided default * ones will be created automatically. */ public function VolumetricPointLight(width:uint, height:uint, occlusion:DisplayObject, colorOrGradient:*, alphas:Array = null, ratios:Array = null) { if(colorOrGradient is Array) { _colors = colorOrGradient.concat(); if(!ratios) _ratios = colorOrGradient.map(function(item:*, i:int, arr:Array):int { return 0x100*i/(colorOrGradient.length+i-1) }); if(!alphas) _alphas = _colors.map(function(..._):Number { return 1 }); } else { _colors = [colorOrGradient, 0]; _ratios = [0, 255]; } super(width, height, _gradientBmp, occlusion); if(!occlusion) throw(new Error("An occlusion DisplayObject must be provided.")); if(!(colorOrGradient is Array || colorOrGradient is uint)) throw(new Error("colorOrGradient must be either an Array or a uint.")); } protected function _drawGradient():void { var size:Number = 2 * Math.sqrt(_viewportWidth*_viewportWidth + _viewportHeight*_viewportHeight); _gradientMtx.createGradientBox(size, size, 0, -size/2 + srcX, -size/2 + srcY); _gradient.graphics.clear(); _gradient.graphics.beginGradientFill(GradientType.RADIAL, _colors, _alphas, _ratios, _gradientMtx); _gradient.graphics.drawRect(0, 0, _viewportWidth, _viewportHeight); _gradient.graphics.endFill(); if(_gradientBmp.bitmapData) _gradientBmp.bitmapData.dispose(); _gradientBmp.bitmapData = new BitmapData(_viewportWidth, _viewportHeight, true, 0); _gradientBmp.bitmapData.draw(_gradient); } /** * Updates the lo-res gradient bitmap if neccesary and copies it to _baseBmd. */ override protected function _drawLoResEmission():void { if(_gradientLoResDirty) { super._drawLoResEmission(); _gradientLoResBmd.copyPixels(_baseBmd, _baseBmd.rect, _baseBmd.rect.topLeft); _gradientLoResDirty = false; } else { _baseBmd.copyPixels(_gradientLoResBmd, _baseBmd.rect, _baseBmd.rect.topLeft); } } /** @inheritDoc */ override protected function _updateBuffers():void { super._updateBuffers(); _gradientLoResBmd = new BitmapData(_bufferWidth, _bufferHeight, false, 0); _gradientLoResDirty = true; } /** @inheritDoc */ override public function setViewportSize(width:uint, height:uint):void { super.setViewportSize(width, height); _drawGradient(); _gradientLoResDirty = true; } /** @inheritDoc */ override public function render(e:Event = null):void { var srcChanged:Boolean = _lastSrcX != srcX || _lastSrcY != srcY; if(srcChanged) _drawGradient(); _gradientLoResDirty ||= srcChanged; _gradientLoResDirty ||= (!colorIntegrity && (_lastIntensity != intensity)); _gradientLoResDirty ||= (_lastColorIntegrity != colorIntegrity); _lastSrcX = srcX; _lastSrcY = srcY; _lastIntensity = intensity; _lastColorIntegrity = colorIntegrity; super.render(e); } /** @inheritDoc */ override public function dispose():void { super.dispose(); if(_gradientLoResBmd) _gradientLoResBmd.dispose(); _gradientLoResBmd = null; } }
Join Effecthub.com
Working with Global Gaming Artists and Developers!
Login
Sign Up
Or Login with Your Email Address:
Email
Password
Remember
Or Sign Up with Your Email Address:
Your Email
This field must contain a valid email
Set Password
Password should be at least 1 character
Stay informed via email