====== Filters ======
This page will contain a detailed reference about fragment filters in the future. At the moment, it is just a placeholder.
Here's the simplest possible filter: a filter that displays the object in exactly the way it was rendered in the first place.
public class IdentityFilter extends FragmentFilter
{
private var mShaderProgram:Program3D;
public function IdentityFilter()
{
super();
}
public override function dispose():void
{
if (mShaderProgram) mShaderProgram.dispose();
super.dispose();
}
protected override function createPrograms():void
{
var fragmentProgramCode:String =
"tex oc, v0, fs0 <2d, clamp, linear, mipnone>"; // just forward texture color
mShaderProgram = assembleAgal(fragmentProgramCode);
}
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.setProgram(mShaderProgram);
}
}
This one does a little more: it converts a colored object into its grayscale version, using specific quantifiers for each color.
public class GrayscaleFilter extends FragmentFilter
{
private var mQuantifiers:Vector.;
private var mShaderProgram:Program3D;
public function GrayscaleFilter(red:Number=0.299, green:Number=0.587, blue:Number=0.114)
{
mQuantifiers = new [red, green, blue, 0.0];
}
public override function dispose():void
{
if (mShaderProgram) mShaderProgram.dispose();
super.dispose();
}
protected override function createPrograms():void
{
var fragmentProgramCode:String =
"tex ft0, v0, fs0 <2d, clamp, linear, mipnone> \n" + // read texture color
"dp3 ft0.xyz, ft0.xyz, fc0.xyz \n" + // dot product color with quantifiers
"mov oc, ft0 \n"; // output color
mShaderProgram = assembleAgal(fragmentProgramCode);
}
protected override function activate(pass:int, context:Context3D, texture:Texture):void
{
context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, mQuantifiers, 1);
context.setProgram(mShaderProgram);
}
}
And another one: an InverseFilter.
public class InverseFilter extends FragmentFilter
{
private var mShaderProgram:Program3D;
private var mOnes:Vector. = new [1.0, 1.0, 1.0, 1.0];
private var mMinColor:Vector. = new [0, 0, 0, 0.0001];
public function InverseFilter()
{
super();
}
public override function dispose():void
{
if (mShaderProgram) mShaderProgram.dispose();
super.dispose();
}
protected override function createPrograms():void
{
// One might expect that we could just subtract the RGB values from 1, right?
// The problem is that the input arrives with premultiplied alpha values, and the
// output is expected in the same form. So we first have to restore the original RGB
// values, subtract them from one, and then multiply with the original alpha again.
var fragmentProgramCode:String =
"tex ft0, v0, fs0 <2d, clamp, linear, mipnone> \n" + // read texture color
"max ft0, ft0, fc1 \n" + // avoid division through zero in next step
"div ft0.xyz, ft0.xyz, ft0.www \n" + // restore original (non-PMA) RGB values
"sub ft0.xyz, fc0.xyz, ft0.xyz \n" + // subtract rgb values from '1'
"mul ft0.xyz, ft0.xyz, ft0.www \n" + // multiply with alpha again (PMA)
"mov oc, ft0 \n"; // copy to output
mShaderProgram = assembleAgal(fragmentProgramCode);
}
protected override function activate(pass:int, context:Context3D, texture:Texture):void
{
context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, mOnes, 1);
context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 1, mMinColor, 1);
context.setProgram(mShaderProgram);
}
}
Those filters are no longer a part of Starling, because you can achieve all three effects with the more flexible "ColorMatrixFilter" class.