Sunday, November 18, 2012

Gradient Shadow Filter Starling

Instead of doing lot of bla,bla... check the code 

*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;
        }
      
    }

}




Usage:


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

5 comments:

  1. 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.
    Thx

    ReplyDelete
  2. There's a problem with the code were you define fc1 and fc2, you're not actually stipulating what type of Vectors they are.

    ReplyDelete
  3. @Jason The blog html generation striping the Number tags :)

    ReplyDelete
  4. Sir can you tell me that how much time it takes to display the ads in your blogger??

    ReplyDelete