浏览代码

[starling] Added two color tinting. Closes part of #843

badlogic 8 年之前
父节点
当前提交
4935284449

二进制
spine-as3/spine-as3-example/lib/spine-as3.swc


+ 1 - 0
spine-as3/spine-as3-example/src/spine/examples/Main.as

@@ -27,6 +27,7 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
+
 package spine.examples {
 	import flash.display.Sprite;
 

+ 1 - 0
spine-as3/spine-as3/.settings/org.eclipse.core.resources.prefs

@@ -1,4 +1,5 @@
 eclipse.preferences.version=1
+encoding//src/spine/SkeletonJson.as=UTF-8
 encoding//src/spine/animation/TwoColorTimeline.as=UTF-8
 encoding//src/spine/attachments/PointAttachment.as=UTF-8
 encoding/<project>=UTF-8

+ 4 - 4
spine-as3/spine-as3/src/spine/SkeletonJson.as

@@ -134,7 +134,7 @@ package spine {
 
 				var dark : String = slotMap["dark"];
 				if (dark) {
-					slotData.darkColor.setFrom(toColor(dark, 0), toColor(dark, 1), toColor(dark, 2), toColor(dark, 3));
+					slotData.darkColor = new Color(toColor(dark, 0), toColor(dark, 1), toColor(dark, 2), 0);					
 				}
 
 				slotData.attachmentName = slotMap["attachment"];
@@ -438,7 +438,7 @@ package spine {
 
 						frameIndex = 0;
 						for each (valueMap in values) {
-							color = valueMap["color"];
+							color = valueMap["light"];
 							var darkColor : String = valueMap["dark"];
 							var light : Color = new Color(0, 0, 0, 0);
 							var dark : Color = new Color(0, 0, 0, 0);
@@ -710,8 +710,8 @@ package spine {
 		}
 
 		static private function toColor(hexString : String, colorIndex : int) : Number {
-			if (hexString.length != 8) throw new ArgumentError("Color hexidecimal length must be 8, received: " + hexString);
-			return parseInt(hexString.substring(colorIndex * 2, colorIndex * 2 + 2), 16) / 255;
+			if (hexString.length != 8 && hexString.length != 6) throw new ArgumentError("Color hexidecimal length must be 6 or 8, received: " + hexString);
+			return parseInt(hexString.substring(colorIndex * 2, colorIndex * 2 + 2), 16) / 255;			
 		}
 
 		static private function getFloatArray(map : Object, name : String, scale : Number) : Vector.<Number> {

+ 3 - 3
spine-as3/spine-as3/src/spine/animation/TwoColorTimeline.as

@@ -103,9 +103,9 @@ package spine.animation {
 				g += (frames[frame + G] - g) * percent;
 				b += (frames[frame + B] - b) * percent;
 				a += (frames[frame + A] - a) * percent;
-				r2 += (frames[frame + R2] - a) * percent;
-				g2 += (frames[frame + G2] - a) * percent;
-				b2 += (frames[frame + B2] - a) * percent;
+				r2 += (frames[frame + R2] - r2) * percent;
+				g2 += (frames[frame + G2] - g2) * percent;
+				b2 += (frames[frame + B2] - b2) * percent;
 			}
 			if (alpha == 1) {
 				slot.color.setFrom(r, g, b, a);

+ 1 - 0
spine-starling/spine-starling-example/.settings/org.eclipse.core.resources.prefs

@@ -1,3 +1,4 @@
 eclipse.preferences.version=1
 encoding//src/spine/examples/TankExample.as=UTF-8
+encoding//src/spine/examples/TwoColorExample.as=UTF-8
 encoding/<project>=UTF-8

二进制
spine-starling/spine-starling-example/lib/spine-as3.swc


二进制
spine-starling/spine-starling-example/lib/spine-starling.swc


+ 13 - 0
spine-starling/spine-starling-example/src/TwoColorTest.atlas

@@ -0,0 +1,13 @@
+
+TwoColorTest.png
+size: 512,512
+format: RGBA8888
+filter: Linear,Linear
+repeat: none
+squareWithBorder
+  rotate: false
+  xy: 2, 2
+  size: 300, 300
+  orig: 300, 300
+  offset: 0, 0
+  index: -1

+ 150 - 0
spine-starling/spine-starling-example/src/TwoColorTest.json

@@ -0,0 +1,150 @@
+{
+"skeleton": { "hash": "5Oji/z9A5lQ/crlH60repeTNBg8", "spine": "3.6.09-beta", "width": 1588, "height": 732, "images": "" },
+"bones": [
+	{ "name": "root" },
+	{ "name": "singleColorTint", "parent": "root", "x": -400 },
+	{ "name": "singleColorTint2", "parent": "root", "x": -400, "y": -383 },
+	{ "name": "twoColorTint", "parent": "root", "x": 800 },
+	{ "name": "twoColorTint2", "parent": "root", "x": 800, "y": -382 },
+	{ "name": "twoColorTint (blackOnly)", "parent": "root" },
+	{ "name": "twoColorTint (blackOnly)2", "parent": "root", "y": -391 },
+	{ "name": "twoColorTint (colorOnly)", "parent": "root", "x": 400 },
+	{ "name": "twoColorTint (colorOnly)2", "parent": "root", "x": 400, "y": -382 }
+],
+"slots": [
+	{ "name": "squareWithBorder", "bone": "singleColorTint", "attachment": "squareWithBorder" },
+	{ "name": "squareWithBorder7", "bone": "singleColorTint2", "attachment": "squareWithBorder" },
+	{ "name": "squareWithBorder2", "bone": "twoColorTint (blackOnly)", "dark": "000000", "attachment": "squareWithBorder" },
+	{ "name": "squareWithBorder8", "bone": "twoColorTint (blackOnly)2", "dark": "000000", "attachment": "squareWithBorder" },
+	{ "name": "squareWithBorder4", "bone": "twoColorTint (colorOnly)", "dark": "000000", "attachment": "squareWithBorder" },
+	{ "name": "squareWithBorder5", "bone": "twoColorTint (colorOnly)2", "dark": "000000", "attachment": "squareWithBorder" },
+	{ "name": "squareWithBorder3", "bone": "twoColorTint", "dark": "000000", "attachment": "squareWithBorder" },
+	{ "name": "squareWithBorder6", "bone": "twoColorTint2", "dark": "000000", "attachment": "squareWithBorder" }
+],
+"skins": {
+	"default": {
+		"squareWithBorder": {
+			"squareWithBorder": { "width": 300, "height": 300 }
+		},
+		"squareWithBorder2": {
+			"squareWithBorder": { "width": 300, "height": 300 }
+		},
+		"squareWithBorder3": {
+			"squareWithBorder": { "width": 300, "height": 300 }
+		},
+		"squareWithBorder4": {
+			"squareWithBorder": { "width": 300, "height": 300 }
+		},
+		"squareWithBorder5": {
+			"squareWithBorder": {
+				"type": "mesh",
+				"uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ],
+				"triangles": [ 1, 2, 3, 1, 3, 0 ],
+				"vertices": [ 150, -150, -150, -150, -197, 99, 183, 155 ],
+				"hull": 4,
+				"edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ],
+				"width": 300,
+				"height": 300
+			}
+		},
+		"squareWithBorder6": {
+			"squareWithBorder": {
+				"type": "mesh",
+				"uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ],
+				"triangles": [ 1, 2, 3, 1, 3, 0 ],
+				"vertices": [ 238, -200, -191, -60, -150, 150, 119, 111 ],
+				"hull": 4,
+				"edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ],
+				"width": 300,
+				"height": 300
+			}
+		},
+		"squareWithBorder7": {
+			"squareWithBorder": {
+				"type": "mesh",
+				"uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ],
+				"triangles": [ 1, 2, 3, 1, 3, 0 ],
+				"vertices": [ 210, -132, -150, -150, -150, 150, 124, 119 ],
+				"hull": 4,
+				"edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ],
+				"width": 300,
+				"height": 300
+			}
+		},
+		"squareWithBorder8": {
+			"squareWithBorder": {
+				"type": "mesh",
+				"uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ],
+				"triangles": [ 1, 2, 3, 1, 3, 0 ],
+				"vertices": [ 150, -150, -150, -150, -97, 58, 86, 62 ],
+				"hull": 4,
+				"edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ],
+				"width": 300,
+				"height": 300
+			}
+		}
+	}
+},
+"animations": {
+	"animation": {
+		"slots": {
+			"squareWithBorder": {
+				"color": [
+					{ "time": 0, "color": "fffffffe" },
+					{ "time": 1, "color": "9e17b3fe" },
+					{ "time": 2, "color": "fffffffe" }
+				]
+			},
+			"squareWithBorder2": {
+				"twoColor": [
+					{ "time": 0, "light": "fffffffe", "dark": "000000" },
+					{ "time": 1, "light": "fffffffe", "dark": "ff0000" },
+					{ "time": 2, "light": "fffffffe", "dark": "000000" }
+				]
+			},
+			"squareWithBorder3": {
+				"twoColor": [
+					{ "time": 0, "light": "fffffffe", "dark": "000000" },
+					{ "time": 1, "light": "80ff00fe", "dark": "001cff" },
+					{ "time": 2, "light": "fffffffe", "dark": "000000" }
+				]
+			},
+			"squareWithBorder4": {
+				"twoColor": [
+					{ "time": 0, "light": "fffffffe", "dark": "000000" },
+					{ "time": 1, "light": "ffd300fe", "dark": "000000" },
+					{ "time": 2, "light": "fffffffe", "dark": "000000" }
+				]
+			},
+			"squareWithBorder5": {
+				"twoColor": [
+					{ "time": 0, "light": "fffffffe", "dark": "000000" },
+					{ "time": 1, "light": "ffd300fe", "dark": "000000" },
+					{ "time": 2, "light": "fffffffe", "dark": "000000" }
+				]
+			},
+			"squareWithBorder6": {
+				"twoColor": [
+					{ "time": 0, "light": "fffffffe", "dark": "000000" },
+					{ "time": 1, "light": "80ff00fe", "dark": "001cff" },
+					{ "time": 2, "light": "fffffffe", "dark": "000000" }
+				]
+			},
+			"squareWithBorder7": {
+				"color": [
+					{ "time": 0, "color": "fffffffe" },
+					{ "time": 1, "color": "9e17b3fe" },
+					{ "time": 2, "color": "fffffffe" }
+				]
+			},
+			"squareWithBorder8": {
+				"twoColor": [
+					{ "time": 0, "light": "fffffffe", "dark": "000000" },
+					{ "time": 1, "light": "fffffffe", "dark": "ff0000" },
+					{ "time": 2, "light": "fffffffe", "dark": "000000" }
+				]
+			}
+		}
+	}
+}
+}

二进制
spine-starling/spine-starling-example/src/TwoColorTest.png


+ 3 - 2
spine-starling/spine-starling-example/src/spine/examples/Main.as

@@ -39,12 +39,13 @@ package spine.examples {
 
 		public function Main() {
 			var example : Class;
-			// example = SpineboyExample;
+			example = SpineboyExample;
 			// example = GoblinsExample;
 			// example = RaptorExample;
 			// example = TankExample;
 			// example = VineExample;
-			example = StretchymanExample;
+			// example = StretchymanExample;
+			example = TwoColorExample;
 
 			_starling = new Starling(example, stage);
 			_starling.enableErrorChecking = true;

+ 71 - 0
spine-starling/spine-starling-example/src/spine/examples/TwoColorExample.as

@@ -0,0 +1,71 @@
+/******************************************************************************
+ * Spine Runtimes Software License v2.5
+ *
+ * Copyright (c) 2013-2016, Esoteric Software
+ * All rights reserved.
+ *
+ * You are granted a perpetual, non-exclusive, non-sublicensable, and
+ * non-transferable license to use, install, execute, and perform the Spine
+ * Runtimes software and derivative works solely for personal or internal
+ * use. Without the written permission of Esoteric Software (see Section 2 of
+ * the Spine Software License Agreement), you may not (a) modify, translate,
+ * adapt, or develop new applications using the Spine Runtimes or otherwise
+ * create derivative works or improvements of the Spine Runtimes or (b) remove,
+ * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
+ * or other intellectual property or proprietary rights notices on or in the
+ * Software, including any copy thereof. Redistributions in binary or source
+ * form must include this license and terms.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
+ * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+package spine.examples {
+	import spine.*;
+	import spine.atlas.Atlas;
+	import spine.attachments.AtlasAttachmentLoader;
+	import spine.attachments.AttachmentLoader;
+	import spine.starling.SkeletonAnimation;
+	import spine.starling.StarlingTextureLoader;
+
+	import starling.core.Starling;
+	import starling.display.Sprite;
+
+	public class TwoColorExample extends Sprite {
+		[Embed(source = "/TwoColorTest.json", mimeType = "application/octet-stream")]
+		static public const VineJson : Class;
+
+		[Embed(source = "/TwoColorTest.atlas", mimeType = "application/octet-stream")]
+		static public const VineAtlas : Class;
+
+		[Embed(source = "/TwoColorTest.png")]
+		static public const VineAtlasTexture : Class;
+		private var skeleton : SkeletonAnimation;
+
+		public function TwoColorExample() {
+			var attachmentLoader : AttachmentLoader;
+			var spineAtlas : Atlas = new Atlas(new VineAtlas(), new StarlingTextureLoader(new VineAtlasTexture()));
+			attachmentLoader = new AtlasAttachmentLoader(spineAtlas);
+
+			var json : SkeletonJson = new SkeletonJson(attachmentLoader);
+			json.scale = 0.5;
+			var skeletonData : SkeletonData = json.readSkeletonData(new VineJson());
+
+			skeleton = new SkeletonAnimation(skeletonData);
+			skeleton.x = 300;
+			skeleton.y = 200;
+			skeleton.state.setAnimationByName(0, "animation", true);
+
+			addChild(skeleton);
+			Starling.juggler.add(skeleton);
+		}
+	}
+}

+ 2 - 0
spine-starling/spine-starling/.settings/org.eclipse.core.resources.prefs

@@ -4,4 +4,6 @@ encoding//src/spine/starling/SkeletonMesh.as=UTF-8
 encoding//src/spine/starling/SkeletonSprite.as=UTF-8
 encoding//src/spine/starling/StarlingAtlasAttachmentLoader.as=UTF-8
 encoding//src/spine/starling/StarlingTextureLoader.as=UTF-8
+encoding//src/spine/starling/TwoColorEffect.as=UTF-8
+encoding//src/spine/starling/TwoColorMeshStyle.as=UTF-8
 encoding/<project>=UTF-8

二进制
spine-starling/spine-starling/lib/spine-as3.swc


+ 47 - 67
spine-starling/spine-starling/src/spine/starling/SkeletonSprite.as

@@ -79,6 +79,7 @@ package spine.starling {
 			var drawOrder : Vector.<Slot> = skeleton.drawOrder;
 			var worldVertices : Vector.<Number> = _tempVertices;
 			var ii : int, iii : int;
+			var attachmentColor: spine.Color;
 			var rgb : uint, a : Number;
 			var dark : uint;
 			var mesh : SkeletonMesh;
@@ -90,59 +91,43 @@ package spine.starling {
 				var slot : Slot = drawOrder[i];
 				if (slot.attachment is RegionAttachment) {
 					var region : RegionAttachment = slot.attachment as RegionAttachment;
-					region.computeWorldVertices(slot.bone, worldVertices, 0, 2);
-					a = slot.color.a * region.color.a;
-					rgb = Color.rgb(r * slot.color.r * region.color.r, g * slot.color.g * region.color.g, b * slot.color.b * region.color.b);
+					verticesLength = 4 * 2;
+					verticesCount = verticesLength >> 1;
+					if (worldVertices.length < verticesLength) worldVertices.length = verticesLength;
+					region.computeWorldVertices(slot.bone, worldVertices, 0, 2);					
 
-					var image : Image = region.rendererObject as Image;
-					if (image == null) {
-						var origImage : Image = Image(AtlasRegion(region.rendererObject).rendererObject);
-						region.rendererObject = image = new Image(origImage.texture);
-						image.style = _twoColorStyle;
-						for (var j : int = 0; j < 4; j++) {
-							var p : Point = origImage.getTexCoords(j);
-							image.setTexCoords(j, p.x, p.y);
-						}
+					mesh = region.rendererObject as SkeletonMesh;
+					if (mesh == null) {
+						if (region.rendererObject is Image)
+							region.rendererObject = mesh = new SkeletonMesh(Image(region.rendererObject).texture);
+						if (region.rendererObject is AtlasRegion)
+							region.rendererObject = mesh = new SkeletonMesh(Image(AtlasRegion(region.rendererObject).rendererObject).texture);
+						
+						indexData = mesh.getIndexData();
+						indices = new <uint>[0, 1, 2, 2, 3, 0];
+						for (ii = 0; ii < indices.length; ii++)
+							indexData.setIndex(ii, indices[ii]);
+						indexData.numIndices = 6;
+						indexData.trim();
 					}
-
-					if (slot.darkColor == null) dark = Color.rgb(0, 0, 0);
-					else dark = Color.rgb(slot.darkColor.r * 255, slot.darkColor.g * 255, slot.darkColor.b * 255);
-
-					image.setVertexPosition(0, worldVertices[2], worldVertices[3]);
-					image.setVertexColor(0, rgb);
-					image.setVertexAlpha(0, a);
-
-					image.setVertexPosition(1, worldVertices[4], worldVertices[5]);
-					image.setVertexColor(1, rgb);
-					image.setVertexAlpha(1, a);
-
-					image.setVertexPosition(2, worldVertices[0], worldVertices[1]);
-					image.setVertexColor(2, rgb);
-					image.setVertexAlpha(2, a);
-
-					image.setVertexPosition(3, worldVertices[6], worldVertices[7]);
-					image.setVertexColor(3, rgb);
-					image.setVertexAlpha(3, a);
-
-					image.setRequiresRedraw();
-					painter.state.blendMode = blendModes[slot.data.blendMode.ordinal];
-					// FIXME set smoothing/filter
-					painter.batchMesh(image);
+					
+					attachmentColor = region.color;
+					uvs = region.uvs;													
 				} else if (slot.attachment is MeshAttachment) {
 					var meshAttachment : MeshAttachment = MeshAttachment(slot.attachment);
 					verticesLength = meshAttachment.worldVerticesLength;
 					verticesCount = verticesLength >> 1;
 					if (worldVertices.length < verticesLength) worldVertices.length = verticesLength;
 					meshAttachment.computeWorldVertices(slot, 0, meshAttachment.worldVerticesLength, worldVertices, 0, 2);
+					
 					mesh = meshAttachment.rendererObject as SkeletonMesh;
 					if (mesh == null) {
 						if (meshAttachment.rendererObject is Image)
 							meshAttachment.rendererObject = mesh = new SkeletonMesh(Image(meshAttachment.rendererObject).texture);
 						if (meshAttachment.rendererObject is AtlasRegion)
-							meshAttachment.rendererObject = mesh = new SkeletonMesh(Image(AtlasRegion(meshAttachment.rendererObject).rendererObject).texture);
-					}
-
-					if (mesh.numIndices != meshAttachment.triangles.length) {
+							meshAttachment.rendererObject = mesh = new SkeletonMesh(Image(AtlasRegion(meshAttachment.rendererObject).rendererObject).texture);						
+						mesh.setStyle(_twoColorStyle);
+						
 						indexData = mesh.getIndexData();
 						indices = meshAttachment.triangles;
 						indicesLength = meshAttachment.triangles.length;
@@ -151,39 +136,34 @@ package spine.starling {
 						}
 						indexData.numIndices = indicesLength;
 						indexData.trim();
-					}
-
-					// FIXME pre-multiplied alpha?
-					a = slot.color.a * meshAttachment.color.a;
-					rgb = Color.rgb(r * slot.color.r * meshAttachment.color.r, g * slot.color.g * meshAttachment.color.g, b * slot.color.b * meshAttachment.color.b);
-
-					if (slot.darkColor == null) dark = Color.rgb(0, 0, 0);
-					else dark = Color.rgb(slot.darkColor.r * 255, slot.darkColor.g * 255, slot.darkColor.b * 255);
-
-					if (mesh.style.vertexFormat != _twoColorStyle.vertexFormat)
-						mesh.style = _twoColorStyle;
-					vertexData = mesh.getVertexData();
-					uvs = meshAttachment.uvs;
-					vertexData.colorize("color", rgb, a);
-					vertexData.colorize("color2", dark);
-					for (ii = 0, iii = 0; ii < verticesCount; ii++, iii += 2) {
-						mesh.setVertexPosition(ii, worldVertices[iii], worldVertices[iii + 1]);
-						mesh.setTexCoords(ii, uvs[iii], uvs[iii + 1]);
-					}
-					vertexData.numVertices = verticesCount;
-					painter.state.blendMode = blendModes[slot.data.blendMode.ordinal];
-					// FIXME set smoothing/filter
-					painter.batchMesh(mesh);
+					}					
+										
+					attachmentColor = meshAttachment.color;
+					uvs = meshAttachment.uvs;					
 				}
+				
+				a = slot.color.a * attachmentColor.a;
+				rgb = Color.rgb(r * slot.color.r * attachmentColor.r, g * slot.color.g * attachmentColor.g, b * slot.color.b * attachmentColor.b);
+				if (slot.darkColor == null) dark = Color.rgb(0, 0, 0);
+				else dark = Color.rgb(slot.darkColor.r * 255, slot.darkColor.g * 255, slot.darkColor.b * 255);	
+
+				// Mesh doesn't retain the style, can't find the reason why
+				mesh.setStyle(_twoColorStyle);			
+				vertexData = mesh.getVertexData();					
+				vertexData.colorize("color", rgb, a);
+				vertexData.colorize("color2", dark);
+				for (ii = 0, iii = 0; ii < verticesCount; ii++, iii += 2) {
+					mesh.setVertexPosition(ii, worldVertices[iii], worldVertices[iii + 1]);
+					mesh.setTexCoords(ii, uvs[iii], uvs[iii + 1]);
+				}
+				vertexData.numVertices = verticesCount;
+				painter.state.blendMode = blendModes[slot.data.blendMode.ordinal];				
+				painter.batchMesh(mesh);
 			}
 			painter.state.blendMode = originalBlendMode;
 		}
 
 		override public function hitTest(localPoint : Point) : DisplayObject {
-			// FIXME what to do here?
-			// if (forTouch && (!visible || !touchable))
-			// return null;
-
 			var minX : Number = Number.MAX_VALUE, minY : Number = Number.MAX_VALUE;
 			var maxX : Number = -Number.MAX_VALUE, maxY : Number = -Number.MAX_VALUE;
 			var slots : Vector.<Slot> = skeleton.slots;

+ 20 - 8
spine-starling/spine-starling/src/spine/starling/TwoColorEffect.as

@@ -29,6 +29,7 @@
  *****************************************************************************/
 
 package spine.starling {
+	import flash.display3D.Context3DProgramType;
 	import starling.rendering.Program;
 
 	import flash.display3D.Context3D;
@@ -40,20 +41,28 @@ package spine.starling {
 		public  static const VERTEX_FORMAT : VertexDataFormat = TwoColorMeshStyle.VERTEX_FORMAT;
 
 		override protected function createProgram() : Program {
-			var vertexShader : String = ["m44 op, va0, vc0", // 4x4 matrix transform to output clip-space 
+			// v0 -> tex coords
+			// v1 -> color plus alpha
+			// v2 -> dark color
+			var vertexShader : String = [
+			"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
+			"mov v2, va3     "  // pass dark color to fp
 			].join("\n");
 
-			var fragmentShader : String = [tex("ft0", "v0", 0, texture) +  // get color from texture 
-			"mul ft0, ft0, v1",             // multiply color with texel color 
-			"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
+			var fragmentShader : String = [
+			tex("ft0", "v0", 0, texture),   	// ft0 = texture2d(texCoords)
+			"mul ft1, ft0, v1",					// ft1 = texColor * light
+			"sub ft2.xyz, fc0.xyz, ft0.xyz",	// ft2.xyz = (1 - texColor.rgb)
+			"mul ft2.xyz, ft2.xyz, v2.xyz",		// ft2.xyz = (1 - texColor.rgb) * dark.rgb
+			"mul ft2.xyz, ft2.xyz, ft1.www",	// ft2.xyz = (1 - texColor.rgb) * dark.rgb * alpha
+			"add ft2.xyz, ft2.xyz, ft1.xyz",	// ft2.xyz = (1 - texColor.rgb) * dark.rgb * alpha + texColor.rgb * light.rgb
+			"mov ft2.w, ft1.w",					// ft2.w = alpha
+			"mov oc, ft2"
 			].join("\n");
 
-			return Program.fromSource(vertexShader, fragmentShader);
+			return Program.fromSource(vertexShader, fragmentShader);			
 		}
 
 		override public function get vertexFormat() : VertexDataFormat {
@@ -63,6 +72,9 @@ package spine.starling {
 		override protected function beforeDraw(context : Context3D) : void {
 			super.beforeDraw(context);
 			vertexFormat.setVertexBufferAt(3, vertexBuffer, "color2");
+			
+			// fc0 -> (1, 1, 1, 1) 
+			context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.<Number>([1, 1, 1, 1]));
 		}
 
 		override protected function afterDraw(context : Context3D) : void {