*Updated 20.11.12 (added radial shadow option)
package filters
{
import starling.core.RenderSupport;
import starling.display.DisplayObject;
import starling.filters.FragmentFilter;
import flash.display3D.Context3D;
import flash.display3D.Context3DProgramType;
import flash.display3D.Program3D;
import starling.textures.Texture;
/**
* ...
* @author winxalex
*/
public class GradientShadowFilter extends FragmentFilter
{
private var mShaderProgram:Program3D;
private static var recStageWidth:Number=NaN;
private static var recStageHeight:Number = NaN;
/**
* Fragment constants vectors
*/
private var fc1:Vector.<Number>
private var fc2:Vector.<Number>
private var _axisX:Boolean;
private var _lightToDark:Boolean;
private var _spreadOffsetX:Number=0;
private var _spreadOffsetY:Number = 0;
private var _xCenter:Number = 0.5;
private var _yCenter:Number = 0.5;
private var _radial:Boolean;
/**
*
* @param axisX
* @param dir
* @param radial (radial or rectangle shadow)
*/
public function GradientShadowFilter(axisX:Boolean=true,lightToDark:Boolean=true,radial:Boolean=false):void
{
fc1 =new Vector.<Number>(4,true);
fc2 = new Vector.<Number>(4, true);
fc2[0] = 1;
fc2[1] = 2;
fc2[2] = 0
fc2[3] = 0;
_axisX = axisX;
_lightToDark = lightToDark;
_radial = radial;
}
public override function dispose():void
{
if (mShaderProgram) mShaderProgram.dispose();
super.dispose();
}
protected override function createPrograms():void
{
var vertexProgramCode:String =
"m44 vt0, va0, vc0 \n" + // 4x4 matrix transform to output space
"mov v1, vt0 \n" + // move position to v1
"mov op, vt0 \n" +//move position to output
"mov v0, va1 "; //move color to output
var fragmentProgramCode:String =
"tex ft0, v0, fs0 <2d data-blogger-escaped-clamp="clamp" data-blogger-escaped-linear="linear" data-blogger-escaped-mipnone="mipnone"> \n" + // read texture color
"mov ft1, v1 \n" +
(_radial ?
"sub ft1.x, ft1.x, fc1.x \n" +// subtruct current x from _clipX
"div ft1.x, ft1.x, fc1.z \n" + // transfer x in clip region from 0-1 (x-_clipX)/_clipWidth
"sub ft1.y, ft1.y, fc1.y \n" +// subtruct current y from _clipY
"div ft1.y, ft1.y, fc1.w \n" + // transfer x in clip region from 0-1 (y-_clipY)/_clipHeight
(!_lightToDark ?
"sub ft1.x, fc2.x, ft1.x \n"
: "sub ft1.y, fc2.x, ft1.y \n" // change direction
) +
(!_axisX ?
"sub ft1.y, ft1.y, fc2.w \n" +// Ycenter position (default:0)
"mul ft1.y, ft1.y, fc2.y \n" // y*2 => half height
:
"sub ft1.x, ft1.x, fc2.z \n" +// Xcenter position (default:0)
"mul ft1.x, ft1.x, fc2.y \n" // x*2 => half width
)+
"mul ft1.y, ft1.y, ft1.y \n" +// y^2
"mul ft1.x, ft1.x, ft1.x \n" +// x^2
"add ft1.z, ft1.x, ft1.y \n" +// x^2 + y^2
"sub ft1.z, fc2.x, ft1.z \n" +// flip shadow direction
"mul ft0.xyz, ft0.xyz, ft1.zzz\n"
: //RECTANGLE
// X - GRADIENT
(_axisX ?
"sub ft1.x, ft1.x, fc1.x \n" +// subtruct current x from _clipX
"div ft1.x, ft1.x, fc1.z \n" + // transfer x in clip region from 0-1 (x-_clipX)/_clipWidth
(_lightToDark ?
"sub ft1.x, fc2.x, ft1.x \n" // change direction
: "") +
"mul ft0.xyz,ft0.xyz, ft1.xxx\n" //make x gradient
// Y - GRADIENT
:
"sub ft1.y, ft1.y, fc1.y \n" +// subtruct current y from _clipY
"div ft1.y, ft1.y, fc1.w \n" + // transfer x in clip region from 0-1 (y-_clipY)/_clipHeight
(_lightToDark ?
"sub ft1.y, fc2.x, ft1.y \n" // change direction (1-y)
: ""
) +
"mul ft0.xyz,ft0.xyz, ft1.yyy\n" //make y gradient
)
)+
//uniform color
//"mul ft0.xyz, ft0.xyz, ft2.www\n" +
"mov oc, ft0";
mShaderProgram = assembleAgal(fragmentProgramCode,vertexProgramCode);
}
override public function render(object:DisplayObject, support:RenderSupport, parentAlpha:Number):void
{
if (isNaN(recStageHeight)) recStageHeight = 1 / object.stage.stageHeight;
if (isNaN(recStageWidth)) recStageWidth = 1 / object.stage.stageWidth;
fc1[2] = ((_spreadOffsetX +object.width) * 2 * object.scaleX)* recStageWidth ;//_clipWidth
fc1[3] = ((_spreadOffsetY+object.height) * 2 * object.scaleY) * recStageHeight ;//_clipHeight
fc1[0] = (2*object.x * recStageWidth)-1;//_clipX
fc1[1] = (2*(object.stage.stageHeight-object.height-object.y) * recStageHeight)-1 ;//_clipY with switch of y direction
fc2[2] = 0.5;
fc2[3] = 0.5;
super.render(object, support, parentAlpha);
}
protected override function activate(pass:int, context:Context3D, texture:Texture):void
{
// already set by super class:
//
// vertex constants 0-3: mvpMatrix (3D)
// vertex attribute 0: vertex position (FLOAT_2)
// vertex attribute 1: texture coordinates (FLOAT_2)
// texture 0: input texture
context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 1, fc1, 1);
context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 2, fc2, 1);
context.setProgram(mShaderProgram);
}
/**
* typical values between -width and +width
*/
public function set spreadOffsetX(value:Number):void
{
_spreadOffsetX = value;
}
/**
* typical values -height to height
*/
public function set spreadOffsetY(value:Number):void
{
_spreadOffsetY = value;
}
/**
* values: 0 : 1 (0 mean center default:0.5)
*/
public function set xCenter(value:Number):void
{
_xCenter = value;
}
/**
* values: 0 : 1 (0 mean center default:0.5)
*/
public function set yCenter(value:Number):void
{
_yCenter = value;
}
}
}
dO = addChild(new Image(Texture.fromBitmap( new StarlingBMP(), false )))
dO.x = 130;
dO.y = 140;
dO.filter = new GradientShadowFilter(true,false);
GradientShadowFilter(dO.filter).spreadOffsetX = -50; //use width-50 px for spreading of shadow
Great that you like it. It would be good to hit recommend to google by clicking g+1 just more audience to have benefit with.
ReplyDeleteThx
There's a problem with the code were you define fc1 and fc2, you're not actually stipulating what type of Vectors they are.
ReplyDeletethanks for sharing!!
ReplyDelete@Jason The blog html generation striping the Number tags :)
ReplyDeleteSir can you tell me that how much time it takes to display the ads in your blogger??
ReplyDelete