Last active
April 23, 2025 17:13
-
-
Save joshtynjala/275aeeb5014e5e7a2d2573182e98c29d to your computer and use it in GitHub Desktop.
A MeshStyle for Starling 2 that allows to add an offset to each color channel of a mesh, as described in the Starling Manual for OpenFL.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ================================================================================================= | |
// | |
// 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.display3D.Context3D; | |
import starling.display.Mesh; | |
import starling.rendering.FilterEffect; | |
import starling.rendering.MeshEffect; | |
import starling.rendering.Program; | |
import starling.rendering.VertexDataFormat; | |
import starling.styles.MeshStyle; | |
class ColorOffsetStyle extends MeshStyle | |
{ | |
public static final VERTEX_FORMAT:VertexDataFormat = | |
MeshStyle.VERTEX_FORMAT.extend("offset:float4"); | |
private var _offsets:Array<Float>; | |
public function new(redOffset:Float=0.0, greenOffset:Float=0.0, | |
blueOffset:Float=0.0, alphaOffset:Float=0.0) | |
{ | |
super(); | |
_offsets = []; | |
_offsets.resize(4); | |
setTo(redOffset, greenOffset, blueOffset, alphaOffset); | |
} | |
public function setTo(redOffset:Float=0.0, greenOffset:Float=0.0, | |
blueOffset:Float=0.0, alphaOffset:Float=0.0):Void | |
{ | |
_offsets[0] = redOffset; | |
_offsets[1] = greenOffset; | |
_offsets[2] = blueOffset; | |
_offsets[3] = alphaOffset; | |
updateVertices(); | |
} | |
override public function copyFrom(meshStyle:MeshStyle):Void | |
{ | |
var colorOffsetStyle:ColorOffsetStyle = Std.downcast(meshStyle, ColorOffsetStyle); | |
if (colorOffsetStyle != null) | |
{ | |
for (i in 0...4) | |
_offsets[i] = colorOffsetStyle._offsets[i]; | |
} | |
super.copyFrom(meshStyle); | |
} | |
override public function createEffect():MeshEffect | |
{ | |
return new ColorOffsetEffect(); | |
} | |
override private function onTargetAssigned(target:Mesh):Void | |
{ | |
updateVertices(); | |
} | |
override private function get_vertexFormat():VertexDataFormat | |
{ | |
return VERTEX_FORMAT; | |
} | |
private function updateVertices():Void | |
{ | |
if (target != null) | |
{ | |
var numVertices:Int = vertexData.numVertices; | |
for (i in 0...numVertices) | |
vertexData.setPoint4D(i, "offset", | |
_offsets[0], _offsets[1], _offsets[2], _offsets[3]); | |
setRequiresRedraw(); | |
} | |
} | |
public var redOffset(get, set):Float; | |
private function get_redOffset():Float { return _offsets[0]; } | |
private function set_redOffset(value:Float):Float | |
{ | |
_offsets[0] = value; | |
updateVertices(); | |
return value; | |
} | |
public var greenOffset(get, set):Float; | |
private function get_greenOffset():Float { return _offsets[1]; } | |
private function set_greenOffset(value:Float):Float | |
{ | |
_offsets[1] = value; | |
updateVertices(); | |
return value; | |
} | |
public var blueOffset(get, set):Float; | |
private function get_blueOffset():Float { return _offsets[2]; } | |
private function set_blueOffset(value:Float):Float | |
{ | |
_offsets[2] = value; | |
updateVertices(); | |
return value; | |
} | |
public var alphaOffset(get, set):Float; | |
private function get_alphaOffset():Float { return _offsets[3]; } | |
private function set_alphaOffset(value:Float):Float | |
{ | |
_offsets[3] = value; | |
updateVertices(); | |
return value; | |
} | |
} | |
private class ColorOffsetEffect extends MeshEffect | |
{ | |
public static final VERTEX_FORMAT:VertexDataFormat = ColorOffsetStyle.VERTEX_FORMAT; | |
public function new() | |
{ | |
super(); | |
} | |
override private function createProgram():Program | |
{ | |
var vertexShader:String; | |
var fragmentShader:String; | |
var addOffset:String = [ | |
"mov ft1, v2", // copy complete offset to ft1 | |
"mul ft1.xyz, v2.xyz, ft0.www", // multiply offset.rgb with alpha (pma!) | |
"add oc, ft0, ft1" // add offset, copy to output | |
].join("\n"); | |
if (texture != null) | |
{ | |
vertexShader = [ | |
"m44 op, va0, vc0", // 4x4 matrix transform to output clip-space | |
"mov v0, va1 ", // pass texture coordinates to fragment program | |
"mul v1, va2, vc4", // multiply alpha (vc4) with color (va2), pass to fp | |
"mov v2, va3 " // pass offset to fp | |
].join("\n"); | |
fragmentShader = [ | |
FilterEffect.tex("ft0", "v0", 0, texture) + | |
"mul ft0, ft0, v1", // multiply color with texel color | |
addOffset | |
].join("\n"); | |
} | |
else | |
{ | |
vertexShader = [ | |
"m44 op, va0, vc0", // 4x4 matrix transform to output clipspace | |
"mul v0, va2, vc4", // multiply alpha (vc4) with color (va2) | |
"mov v2, va3 " // pass offset to fp | |
].join("\n"); | |
fragmentShader = [ | |
"mov ft0, v0", addOffset | |
].join("\n"); | |
} | |
return Program.fromSource(vertexShader, fragmentShader); | |
} | |
override private function get_vertexFormat():VertexDataFormat | |
{ | |
return VERTEX_FORMAT; | |
} | |
override private function beforeDraw(context:Context3D):Void | |
{ | |
super.beforeDraw(context); | |
vertexFormat.setVertexBufferAt(3, vertexBuffer, "offset"); | |
} | |
override private function afterDraw(context:Context3D):Void | |
{ | |
context.setVertexBufferAt(3, null); | |
super.afterDraw(context); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See Starling Manual for OpenFL: Custom Styles for details.