Here’s the MeshStyle/MeshEffect I used. The AGAL is simple. The fragment shader only has one line, setting a colour. But the colour is calculated in the vertex shader, by multiplying _argb
for that Mesh by the vertex colour. Then as that’s put in a varying register it’s interpolated across the Mesh's triangles, as it would have been without the applied colour.
The problem with it was that each time the colour _argb
changed it needed to start a new draw call, as indicated by the canBatchWith
. The more I use I made of it the more draw calls I had, which eventually drove me to abandon this and use the default MeshStyle, changing vertex colours instead.
package Game.Mesh {
import starling.rendering.MeshEffect;
import starling.styles.MeshStyle;
import starling.rendering.RenderState;
public final class BaseMeshStyle extends MeshStyle {
private var _argb:uint = 0xff707070;
public function BaseMeshStyle(argb:uint = 0xff606060) {
_argb = argb;
}
public function get iARGB():uint{return _argb;}
public function set iARGB(val:uint):void {_argb = val;}
public override function canBatchWith(meshStyle:MeshStyle):Boolean {
if (type == meshStyle.type) {
var style:BaseMeshStyle = meshStyle as BaseMeshStyle;
return (style._argb == _argb);
}
else return false;
}
public override function copyFrom(meshStyle:MeshStyle):void {
var style:BaseMeshStyle = meshStyle as BaseMeshStyle;
_argb = style._argb;
super.copyFrom(meshStyle);
}
public override function createEffect():MeshEffect {
return new BaseMeshEffect(_argb) as MeshEffect;
}
public override function updateEffect(
meshEffect:MeshEffect, state:RenderState):void {
var effect:BaseMeshEffect = meshEffect as BaseMeshEffect;
effect.iARGB = _argb;
super.updateEffect(effect, state);
}
}
}
import flash.display3D.Context3D;
import flash.display3D.Context3DProgramType;
import starling.rendering.MeshEffect;
import starling.rendering.Program;
import starling.rendering.VertexDataFormat;
import starling.utils.Color;
class BaseMeshEffect extends MeshEffect {
private static var aCol :Vector.<Number> = new Vector.<Number>(4, true);
private var _argb :uint;
public function BaseMeshEffect(argb:uint) {_argb = argb;}
public function set iARGB(val:uint):void {_argb = val;}
// only one program
override protected function get programVariantName():uint {return 0xeffec7;}
override protected function createProgram():Program {
var vertexShader:String =
"m44 op, va0, vc0 \n" + // 4x4 matrix transform to output clipspace
"mul v0, va2, vc5 \n"; // apply shading + alpha
var fragmentShader:String =
"mov oc, v0 \n"; // output colour
return Program.fromSource(vertexShader, fragmentShader);
}
override protected function beforeDraw(context:Context3D):void {
var fAlpha:Number;
// call mesh setup
super.beforeDraw(context);
// unpack
Color.toVector(_argb, aCol);
// combine shading with premultiply alpha stage
fAlpha = aCol[3];
aCol[0] *= fAlpha;
aCol[1] *= fAlpha;
aCol[2] *= fAlpha;
context.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 5, aCol);
}
}