Skip to content

Instantly share code, notes, and snippets.

@joshtynjala
Last active April 23, 2025 17:13
Show Gist options
  • Save joshtynjala/974f6f3f49bad9a788e8a7f252d77e5f to your computer and use it in GitHub Desktop.
Save joshtynjala/974f6f3f49bad9a788e8a7f252d77e5f to your computer and use it in GitHub Desktop.
The revised ColorOffsetFilter of the tutorial from the Starling Manual for OpenFL; now with fixed PMA handling.
// =================================================================================================
//
// Starling Framework
// Copyright Gamua GmbH. All Rights Reserved.
//
// This program is free software. You can redistribute and/or modify it
// in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================
package starling.extensions;
import openfl.Vector;
import openfl.display3D.Context3D;
import openfl.display3D.Context3DProgramType;
import starling.filters.FragmentFilter;
import starling.rendering.FilterEffect;
import starling.rendering.Program;
class ColorOffsetFilter extends FragmentFilter
{
public function new(redOffset:Float=0.0, greenOffset:Float=0.0,
blueOffset:Float=0.0, alphaOffset:Float=0.0)
{
super();
colorOffsetEffect.redOffset = redOffset;
colorOffsetEffect.greenOffset = greenOffset;
colorOffsetEffect.blueOffset = blueOffset;
colorOffsetEffect.alphaOffset = alphaOffset;
}
override private function createEffect():FilterEffect
{
return new ColorOffsetEffect();
}
private var colorOffsetEffect(get, never):ColorOffsetEffect;
private function get_colorOffsetEffect():ColorOffsetEffect
{
return cast(effect, ColorOffsetEffect);
}
public var redOffset(get, set):Float;
private function get_redOffset():Float { return colorOffsetEffect.redOffset; }
private function set_redOffset(value:Float):Float
{
colorOffsetEffect.redOffset = value;
setRequiresRedraw();
return value;
}
public var greenOffset(get, set):Float;
private function get_greenOffset():Float { return colorOffsetEffect.greenOffset; }
private function set_greenOffset(value:Float):Float
{
colorOffsetEffect.greenOffset = value;
setRequiresRedraw();
return value;
}
public var blueOffset(get, set):Float;
private function get_blueOffset():Float { return colorOffsetEffect.blueOffset; }
private function set_blueOffset(value:Float):Float
{
colorOffsetEffect.blueOffset = value;
setRequiresRedraw();
return value;
}
public var alphaOffset(get, set):Float;
private function get_alphaOffset():Float { return colorOffsetEffect.alphaOffset; }
private function set_alphaOffset(value:Float):Float
{
colorOffsetEffect.alphaOffset = value;
setRequiresRedraw();
return value;
}
}
private class ColorOffsetEffect extends FilterEffect
{
private var _offsets:Vector<Float>;
private static final MIN_COLOR:Vector<Float> = Vector.ofArray([0, 0, 0, 0.001]);
public function new()
{
super();
_offsets = new Vector(4, true);
}
override private function createProgram():Program
{
var vertexShader:String = FilterEffect.STD_VERTEX_SHADER;
var fragmentShader:String = [
FilterEffect.tex("ft0", "v0", 0, texture), // get color from texture
"mov ft1, fc0", // copy complete offset to ft1
"mul ft1.xyz, fc0.xyz, ft0.www", // multiply offset.rgb with alpha (pma!)
"add oc, ft0, ft1 " // add offset, copy to output
].join("\n");
return Program.fromSource(vertexShader, fragmentShader);
}
override private function beforeDraw(context:Context3D):Void
{
context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, _offsets);
context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 1, MIN_COLOR);
super.beforeDraw(context);
}
public var redOffset(get, set):Float;
private function get_redOffset():Float { return _offsets[0]; }
private function set_redOffset(value:Float):Float { return _offsets[0] = value; }
public var greenOffset(get, set):Float;
private function get_greenOffset():Float { return _offsets[1]; }
private function set_greenOffset(value:Float):Float { return _offsets[1] = value; }
public var blueOffset(get, set):Float;
private function get_blueOffset():Float { return _offsets[2]; }
private function set_blueOffset(value:Float):Float { return _offsets[2] = value; }
public var alphaOffset(get, set):Float;
private function get_alphaOffset():Float { return _offsets[3]; }
private function set_alphaOffset(value:Float):Float { return _offsets[3] = value; }
}
@joshtynjala
Copy link
Author

joshtynjala commented Apr 23, 2025

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment