     private var _paramsDirty:Boolean            = true;
     private var _strengthsDirty:Boolean         = true;
 
-    private var _strengths:Vector.<Number>      = new <Number>[];
+    protected var _strengths:Vector.<Number>    = new <Number>[];
     private var _offsets:Vector.<Number>        = new <Number>[0, 0, 0, 0];
     private var _uv:Vector.<Number>             = new <Number>[0, 1, 0, 1];
     private var _pixelSize:Vector.<Number>      = new <Number>[Number.NaN, Number.NaN, Number.NaN, Number.NaN];
 
+    // shader constants
+    protected var uvCenter:IRegister            = VARYING[0];
+    protected var weightCenter:IComponent       = CONST[0].x;
+    protected var weightOne:IComponent          = CONST[0].y;
+    protected var weightTwo:IComponent          = CONST[0].z;
+    protected var offsetOne:IField              = CONST[1].xy;
+    protected var offsetTwo:IField              = CONST[1].zw;
+    protected var uMin:IComponent               = CONST[2].x;
+    protected var uMax:IComponent               = CONST[2].y;
+    protected var vMin:IComponent               = CONST[2].z;
+    protected var vMax:IComponent               = CONST[2].w;
+    protected var halfPixelWidth:IComponent     = CONST[3].z;
+    protected var halfPixelHeight:IComponent    = CONST[3].w;
+
     public function get type():String { return _type; }
     public function set type(value:String):void {
         if(value == _type)

    public static const HORIZONTAL:String   = "horizontal";
    public static const VERTICAL:String     = "vertical";

    private static const DEFAULT_FIRST_PASS_STRENGTH:Number                 = 1.25;
    private static const DEFAULT_STRENGTH_INCREASE_PER_PASS_RATIO:Number    = 2.5;

    private static var _verticalOffsets:Vector.<Number>     = new <Number>[0.0, 1.3846153846, 0.0, 3.2307692308];
    private static var _horizontalOffsets:Vector.<Number>   = new <Number>[1.3846153846, 0.0, 3.2307692308, 0.0];

        if(_paramsDirty)
            updateParameters();

        context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, _weights);
        context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 1, _offsets);
        context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 2, _uv);
        context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 3, _pixelSize);
    }

    public function deactivate(context:Context3D):void { }

    override protected function _vertexShader():void {
        comment("Apply a 4x4 matrix to transform vertices to clip-space");
        multiply4x4(OUTPUT, ATTRIBUTE[0], CONST[0]);

        comment("Pass uv coordinates to fragment shader");
        move(uvCenter, ATTRIBUTE[1]);

//        comment("pass 4 additional UVs for sampling neighbours, in order: -2, -1, +1, +2 pixels away");
//        subtract(uvMinusTwo, ATTRIBUTE[1], CONST[4].zw);
//        subtract(uvMinusOne, ATTRIBUTE[1], CONST[4].xy);
//        add(uvPlusOne, ATTRIBUTE[1], CONST[4].xy);
//        add(uvPlusTwo, ATTRIBUTE[1], CONST[4].zw);
    }

    override protected function _fragmentShader():void {
        var tempColor:IRegister     = TEMP[0];
        var outputColor:IRegister   = TEMP[1];
        var uv:IRegister            = TEMP[2];

        sampleColor(outputColor, uvCenter, weightCenter);

        subtract(uv, uvCenter, offsetTwo);
        sampleColor(tempColor, uv, weightTwo, uMin, uMax, vMin, vMax, halfPixelWidth, halfPixelHeight, TEMP[6]);
        add(outputColor, outputColor, tempColor);

        subtract(uv, uvCenter, offsetOne);
        sampleColor(tempColor, uv, weightOne, uMin, uMax, vMin, vMax, halfPixelWidth, halfPixelHeight, TEMP[6]);
        add(outputColor, outputColor, tempColor);

        add(uv, uvCenter, offsetOne);
        sampleColor(tempColor, uv, weightOne, uMin, uMax, vMin, vMax, halfPixelWidth, halfPixelHeight, TEMP[6]);
        add(outputColor, outputColor, tempColor);

        add(uv, uvCenter, offsetTwo);
        sampleColor(tempColor, uv, weightTwo, uMin, uMax, vMin, vMax, halfPixelWidth, halfPixelHeight, TEMP[6]);
        add(outputColor, outputColor, tempColor);

        move(OUTPUT, outputColor);
    }

    protected function sampleColor(sampledColor:IRegister, uv:IRegister, colorWeight:IComponent, minU:IComponent = null, maxU:IComponent = null, minV:IComponent = null, maxV:IComponent = null, halfPixelWidth:IComponent = null, halfPixelHeight:IComponent = null, temp:IRegister = null):void {
        if(minU != null) {
            ShaderUtil.clamp(uv.x, minU, maxU, halfPixelWidth, temp);
            ShaderUtil.clamp(uv.y, minV, maxV, halfPixelHeight, temp);
        }

        sampleTexture(sampledColor, uv, SAMPLER[0], TEXTURE_FLAGS);
        multiply(sampledColor, sampledColor, colorWeight);
    }

    private function updateParameters():void {
