Browse Source

[unity] Added support for Tint Black at all Spine URP shaders (2D and 3D) and at `Spine/Sprite` shaders. Closes #1705.

Harald Csaszar 2 years ago
parent
commit
1fa6c2edbb
27 changed files with 317 additions and 27 deletions
  1. 2 0
      CHANGELOG.md
  2. 15 0
      spine-unity/Assets/Spine/Editor/spine-unity/Editor/Shaders/SpineSpriteShaderGUI.cs
  3. 4 0
      spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/CGIncludes/Spine-Skeleton-Lit-Common.cginc
  4. 38 4
      spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/CGIncludes/ShaderShared.cginc
  5. 5 0
      spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/CGIncludes/SpriteLighting.cginc
  6. 21 2
      spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/CGIncludes/SpritePixelLighting.cginc
  7. 23 1
      spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/CGIncludes/SpriteUnlit.cginc
  8. 19 2
      spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/CGIncludes/SpriteVertexLighting.cginc
  9. 3 0
      spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/SpritesPixelLit.shader
  10. 4 0
      spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/SpritesUnlit.shader
  11. 3 0
      spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/SpritesVertexLit.shader
  12. 1 1
      spine-unity/Assets/Spine/package.json
  13. 20 1
      spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/2D/Include/Spine-Sprite-StandardPass-URP-2D.hlsl
  14. 4 0
      spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/2D/Spine-Skeleton-URP-2D.shader
  15. 44 5
      spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/2D/Spine-SkeletonLit-URP-2D.shader
  16. 3 0
      spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/2D/Spine-Sprite-URP-2D.shader
  17. 3 0
      spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Include/Spine-Input-Sprite-URP.hlsl
  18. 6 0
      spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Include/Spine-Input-URP.hlsl
  19. 17 2
      spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Include/Spine-Skeleton-ForwardPass-URP.hlsl
  20. 28 7
      spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Include/Spine-SkeletonLit-ForwardPass-URP.hlsl
  21. 29 1
      spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Include/Spine-Sprite-ForwardPass-URP.hlsl
  22. 3 0
      spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Include/SpineCoreShaders/Spine-Skeleton-Tint-Common.cginc
  23. 10 0
      spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Include/SpineCoreShaders/Spine-Skeleton-Tint-Common.cginc.meta
  24. 4 0
      spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Spine-Skeleton-URP.shader
  25. 4 0
      spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Spine-SkeletonLit-URP.shader
  26. 3 0
      spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Spine-Sprite-URP.shader
  27. 1 1
      spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/package.json

+ 2 - 0
CHANGELOG.md

@@ -101,6 +101,7 @@
   * Added previously missing unlit URP 2D shader variant, available under `Universal Render Pipeline/2D/Spine/Skeleton`.
   * Added support for light cookies at `Universal Render Pipeline/Spine/Sprite` shader.
   * Timeline extension package: An additional Spine preferences parameter `Timeline` - `Default Mix Duration` has been added, setting newly added `SpineAnimationStateClip` clips accordingly, defaults to false. This Spine preferences parameter can be enabled to default to the previous behaviour before this update.
+  * Tint Black: Added support for [Tint Black](http://en.esotericsoftware.com/spine-slots#Tint-black) functionality at all Spine URP shaders (2D and 3D shaders) and at all standard pipeline `Spine/Sprite` shaders. This feature can be enabled via the `Tint Black` material parameter in the Inspector. Note: The URP Sprite shaders provided in the Spine URP Shaders extension UPM package require the latest version of the spine-unity runtime (package version 4.1.12, 2023-05-31 or newer) to display the added material parameters in the Inspector GUI.
  
 * **Breaking changes**
   * Made `SkeletonGraphic.unscaledTime` parameter protected, use the new property `UnscaledTime` instead.
@@ -109,6 +110,7 @@
 * **Changes of default values**
 
 * **Deprecated**
+  * Shader macro `RETURN_UNLIT_IF_ADDITIVE_SLOT` in `spine-unity/Shaders/Sprite/CGIncludes/ShaderShared.cginc` has been deprecated and will be removed in spine-unity 4.2. Use RETURN_UNLIT_IF_ADDITIVE_SLOT_TINT instead.
 
 * **Restructuring (Non-Breaking)**
 

+ 15 - 0
spine-unity/Assets/Spine/Editor/spine-unity/Editor/Shaders/SpineSpriteShaderGUI.cs

@@ -130,6 +130,8 @@ public class SpineSpriteShaderGUI : SpineShaderWithOutlineGUI {
 	MaterialProperty _smoothnessScale = null;
 
 	MaterialProperty _lightAffectsAdditive = null;
+	MaterialProperty _tintBlack = null;
+	MaterialProperty _darkColor = null;
 
 	static GUIContent _albedoText = new GUIContent("Albedo", "Albedo (RGB) and Transparency (A)");
 	static GUIContent _maskText = new GUIContent("Light Mask", "Light mask texture (secondary Sprite texture)");
@@ -192,6 +194,8 @@ public class SpineSpriteShaderGUI : SpineShaderWithOutlineGUI {
 	static GUIContent _meshRequiresNormalsAndTangentsText = new GUIContent("Note: Material requires a mesh with Normals and Tangents.");
 	static GUIContent[] _fixedDiffuseRampModeOptions = { new GUIContent("Hard"), new GUIContent("Soft"), new GUIContent("Old Hard"), new GUIContent("Old Soft") };
 	static GUIContent _lightAffectsAdditiveText = new GUIContent("Light Affects Additive", "For PMA Additive Slots: When enabled, additive Slots are lit normally before the additive color is written to the target buffer. When disabled, the additive color is directly written with intensity 1.");
+	static GUIContent _tintBlackText = new GUIContent("Tint Black", "Enable Tint Black functionality.");
+	static GUIContent _darkColorText = new GUIContent("Dark Color", "Tint-black dark color.");
 
 	const string _primaryMapsText = "Main Maps";
 	const string _depthLabelText = "Depth";
@@ -266,6 +270,8 @@ public class SpineSpriteShaderGUI : SpineShaderWithOutlineGUI {
 		_smoothnessScale = FindProperty("_GlossMapScale", props, false);
 
 		_lightAffectsAdditive = FindProperty("_LightAffectsAdditive", props, false);
+		_tintBlack = FindProperty("_TintBlack", props, false);
+		_darkColor = FindProperty("_Black", props, false);
 	}
 
 	static bool BoldToggleField (GUIContent label, bool value) {
@@ -851,6 +857,15 @@ public class SpineSpriteShaderGUI : SpineShaderWithOutlineGUI {
 			_materialEditor.ShaderProperty(_lightAffectsAdditive, _lightAffectsAdditiveText);
 			dataChanged |= EditorGUI.EndChangeCheck();
 		}
+
+		if (_tintBlack != null) {
+			EditorGUI.BeginChangeCheck();
+			_materialEditor.ShaderProperty(_tintBlack, _tintBlackText);
+			dataChanged |= EditorGUI.EndChangeCheck();
+
+			if (_darkColor != null && (_tintBlack.floatValue != 0 || _tintBlack.hasMixedValue))
+				_materialEditor.ShaderProperty(_darkColor, _darkColorText);
+		}
 		return dataChanged;
 	}
 

+ 4 - 0
spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/CGIncludes/Spine-Skeleton-Lit-Common.cginc

@@ -65,6 +65,10 @@ struct appdata {
 	float3 normal : NORMAL;
 	half4 color : COLOR;
 	float2 uv0 : TEXCOORD0;
+#if defined(_TINT_BLACK_ON)
+	float2 tintBlackRG : TEXCOORD1;
+	float2 tintBlackB : TEXCOORD2;
+#endif
 	UNITY_VERTEX_INPUT_INSTANCE_ID
 };
 

+ 38 - 4
spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/CGIncludes/ShaderShared.cginc

@@ -134,12 +134,18 @@ inline half3 calculateNormalFromBumpMap(float2 texUV, half3 tangentWorld, half3
 //
 inline fixed4 prepareLitPixelForOutput(fixed4 finalPixel, fixed textureAlpha, fixed colorAlpha) : SV_Target
 {
+#if defined(_TINT_BLACK_ON)
+	const bool applyPMA = false;
+#else
+	const bool applyPMA = true;
+#endif
+
 #if defined(_ALPHABLEND_ON)
 	//Normal Alpha
-	finalPixel.rgb *= finalPixel.a;
+	if (applyPMA) finalPixel.rgb *= finalPixel.a;
 #elif defined(_ALPHAPREMULTIPLY_VERTEX_ONLY)
 	//PMA vertex, straight texture
-	finalPixel.rgb *= textureAlpha;
+	if (applyPMA) finalPixel.rgb *= textureAlpha;
 #elif defined(_ALPHAPREMULTIPLY_ON)
 	//Pre multiplied alpha, both vertex and texture
 	// texture and vertex colors are premultiplied already
@@ -153,10 +159,10 @@ inline fixed4 prepareLitPixelForOutput(fixed4 finalPixel, fixed textureAlpha, fi
 #elif defined(_ADDITIVEBLEND)
 	//Additive
 	finalPixel *= 2.0f;
-	finalPixel.rgb *= colorAlpha;
+	if (applyPMA) finalPixel.rgb *= colorAlpha;
 #elif defined(_ADDITIVEBLEND_SOFT)
 	//Additive soft
-	finalPixel.rgb *= finalPixel.a;
+	if (applyPMA) finalPixel.rgb *= finalPixel.a;
 #else
 	//Opaque
 	finalPixel.a = 1;
@@ -166,7 +172,11 @@ inline fixed4 prepareLitPixelForOutput(fixed4 finalPixel, fixed textureAlpha, fi
 
 inline fixed4 calculateLitPixel(fixed4 texureColor, fixed4 color, fixed3 lighting) : SV_Target
 {
+#if !defined(_TINT_BLACK_ON)
 	fixed4 finalPixel = texureColor * color * fixed4(lighting, 1);
+#else
+	fixed4 finalPixel = texureColor * fixed4(lighting, 1);
+#endif
 	finalPixel = prepareLitPixelForOutput(finalPixel, texureColor.a, color.a);
 	return finalPixel;
 }
@@ -253,6 +263,8 @@ uniform fixed _Cutoff;
 // Additive Slot blend mode
 // return unlit textureColor, alpha clip textureColor.a only
 //
+// [Deprecated] RETURN_UNLIT_IF_ADDITIVE_SLOT macro will be removed in future versions.
+// Use RETURN_UNLIT_IF_ADDITIVE_SLOT_TINT instead.
 #if defined(_ALPHAPREMULTIPLY_ON) && !defined(_LIGHT_AFFECTS_ADDITIVE)
 	#define RETURN_UNLIT_IF_ADDITIVE_SLOT(textureColor, vertexColor) \
 	if (vertexColor.a == 0 && (vertexColor.r || vertexColor.g || vertexColor.b)) {\
@@ -269,12 +281,34 @@ uniform fixed _Cutoff;
 	#define RETURN_UNLIT_IF_ADDITIVE_SLOT(textureColor, vertexColor)
 #endif
 
+// Replacement for deprecated RETURN_UNLIT_IF_ADDITIVE_SLOT macro.
+#if (defined(_ALPHAPREMULTIPLY_ON) || defined(_ALPHAPREMULTIPLY_VERTEX_ONLY)) && !defined(_LIGHT_AFFECTS_ADDITIVE)
+	#if defined(_TINT_BLACK_ON)
+		#define TINTED_RESULT_PIXEL(textureColor, vertexColor, darkVertexColor, lightColorA, darkColorA) fragTintedColor(texureColor, darkVertexColor, vertexColor, lightColorA, darkColorA)
+	#elif defined(_ALPHAPREMULTIPLY_VERTEX_ONLY)
+		#define TINTED_RESULT_PIXEL(textureColor, vertexColor, darkVertexColor, lightColorA, darkColorA) (texureColor * texureColor.a * vertexColor)
+	#else
+		#define TINTED_RESULT_PIXEL(textureColor, vertexColor, darkVertexColor, lightColorA, darkColorA) (texureColor * vertexColor)
+	#endif
+
+	#define RETURN_UNLIT_IF_ADDITIVE_SLOT_TINT(textureColor, vertexColor, darkVertexColor, lightColorA, darkColorA) \
+	if (vertexColor.a == 0 && (vertexColor.r || vertexColor.g || vertexColor.b)) {\
+		ALPHA_CLIP(texureColor, fixed4(1, 1, 1, 1))\
+		return TINTED_RESULT_PIXEL(textureColor, vertexColor, darkVertexColor, lightColorA, darkColorA);\
+	}
+#else
+	#define RETURN_UNLIT_IF_ADDITIVE_SLOT_TINT(textureColor, vertexColor, darkVertexColor, lightColorA, darkColorA)
+#endif
+
 ////////////////////////////////////////
 // Color functions
 //
 
 #if !defined(USE_LWRP) && !defined(USE_URP)
 uniform fixed4 _Color;
+	#if defined(_TINT_BLACK_ON)
+	uniform fixed4 _Black;
+	#endif
 #endif
 
 inline fixed4 calculateVertexColor(fixed4 color)

+ 5 - 0
spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/CGIncludes/SpriteLighting.cginc

@@ -26,7 +26,12 @@ struct VertexInput
 #if defined(_NORMALMAP)
 	float4 tangent : TANGENT;
 #endif // _NORMALMAP
+#if defined(_TINT_BLACK_ON)
+	float2 tintBlackRG : TEXCOORD1;
+	float2 tintBlackB : TEXCOORD2;
+#endif
 	UNITY_VERTEX_INPUT_INSTANCE_ID
+
 };
 
 ////////////////////////////////////////

+ 21 - 2
spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/CGIncludes/SpritePixelLighting.cginc

@@ -5,6 +5,12 @@
 #include "SpriteLighting.cginc"
 #include "SpriteSpecular.cginc"
 #include "AutoLight.cginc"
+#if defined(_ALPHAPREMULTIPLY_ON)
+	#undef _STRAIGHT_ALPHA_INPUT
+#else
+	#define _STRAIGHT_ALPHA_INPUT
+#endif
+#include "../../CGIncludes/Spine-Skeleton-Tint-Common.cginc"
 
 ////////////////////////////////////////
 // Defines
@@ -19,11 +25,13 @@
 	#define _LIGHT_COORD_INDEX_0 6
 	#define _LIGHT_COORD_INDEX_1 7
 	#define _FOG_COORD_INDEX 8
+	#define _DARKCOLOR_TEXCOORD_INDEX TEXCOORD9
 #else
 	#define _VERTEX_LIGHTING_INDEX TEXCOORD3
 	#define _LIGHT_COORD_INDEX_0 4
 	#define _LIGHT_COORD_INDEX_1 5
 	#define _FOG_COORD_INDEX 6
+	#define _DARKCOLOR_TEXCOORD_INDEX TEXCOORD7
 #endif // _NORMALMAP
 
 struct VertexOutput
@@ -43,6 +51,10 @@ struct VertexOutput
 	UNITY_FOG_COORDS(_FOG_COORD_INDEX)
 #endif // _FOG
 
+#if defined(_TINT_BLACK_ON)
+	float3 darkColor : _DARKCOLOR_TEXCOORD_INDEX;
+#endif
+
 	UNITY_VERTEX_OUTPUT_STEREO
 };
 
@@ -130,11 +142,14 @@ VertexOutput vert(VertexInput v)
 {
 	VertexOutput output;
 
-	UNITY_SETUP_INSTANCE_ID(input);
+	UNITY_SETUP_INSTANCE_ID(v);
     UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
 
 	output.pos = calculateLocalPos(v.vertex);
 	output.color = calculateVertexColor(v.color);
+#if defined(_TINT_BLACK_ON)
+	output.darkColor = GammaToTargetSpace(half3(v.tintBlackRG.r, v.tintBlackRG.g, v.tintBlackB.r)) + _Black.rgb;
+#endif
 	output.texcoord = calculateTextureCoord(v.texcoord);
 	output.posWorld = calculateWorldPos(v.vertex);
 
@@ -166,9 +181,13 @@ VertexOutput vert(VertexInput v)
 fixed4 fragBase(VertexOutput input) : SV_Target
 {
 	fixed4 texureColor = calculateTexturePixel(input.texcoord);
-	RETURN_UNLIT_IF_ADDITIVE_SLOT(texureColor, input.color) // shall be called before ALPHA_CLIP
+	RETURN_UNLIT_IF_ADDITIVE_SLOT_TINT(texureColor, input.color, input.darkColor, _Color.a, _Black.a) // shall be called before ALPHA_CLIP
 	ALPHA_CLIP(texureColor, input.color)
 
+#if defined(_TINT_BLACK_ON)
+	texureColor = fragTintedColor(texureColor, input.darkColor, input.color, _Color.a, _Black.a);
+#endif
+
 	//Get normal direction
 	fixed3 normalWorld = calculateNormalWorld(input);
 

+ 23 - 1
spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/CGIncludes/SpriteUnlit.cginc

@@ -2,6 +2,12 @@
 #define SPRITE_UNLIT_INCLUDED
 
 #include "ShaderShared.cginc"
+#if defined(_ALPHAPREMULTIPLY_ON)
+	#undef _STRAIGHT_ALPHA_INPUT
+#else
+	#define _STRAIGHT_ALPHA_INPUT
+#endif
+#include "../../CGIncludes/Spine-Skeleton-Tint-Common.cginc"
 
 ////////////////////////////////////////
 // Vertex structs
@@ -12,6 +18,10 @@ struct VertexInput
 	float4 vertex : POSITION;
 	float4 texcoord : TEXCOORD0;
 	fixed4 color : COLOR;
+#if defined(_TINT_BLACK_ON)
+	float2 tintBlackRG : TEXCOORD1;
+	float2 tintBlackB : TEXCOORD2;
+#endif
 	UNITY_VERTEX_INPUT_INSTANCE_ID
 };
 
@@ -24,6 +34,10 @@ struct VertexOutput
 	UNITY_FOG_COORDS(1)
 #endif // _FOG
 
+#if defined(_TINT_BLACK_ON)
+	float3 darkColor : TEXCOORD2;
+#endif
+
 	UNITY_VERTEX_OUTPUT_STEREO
 };
 
@@ -41,6 +55,9 @@ VertexOutput vert(VertexInput input)
 	output.pos = calculateLocalPos(input.vertex);
 	output.texcoord = calculateTextureCoord(input.texcoord);
 	output.color = calculateVertexColor(input.color);
+#if defined(_TINT_BLACK_ON)
+	output.darkColor = GammaToTargetSpace(half3(input.tintBlackRG.r, input.tintBlackRG.g, input.tintBlackB.r)) + _Black.rgb;
+#endif
 
 #if defined(_FOG)
 	UNITY_TRANSFER_FOG(output,output.pos);
@@ -55,8 +72,13 @@ VertexOutput vert(VertexInput input)
 fixed4 frag(VertexOutput input) : SV_Target
 {
 	fixed4 texureColor = calculateTexturePixel(input.texcoord.xy);
-	RETURN_UNLIT_IF_ADDITIVE_SLOT(texureColor, input.color) // shall be called before ALPHA_CLIP
+	RETURN_UNLIT_IF_ADDITIVE_SLOT_TINT(texureColor, input.color, input.darkColor, _Color.a, _Black.a) // shall be called before ALPHA_CLIP
 	ALPHA_CLIP(texureColor, input.color)
+
+#if defined(_TINT_BLACK_ON)
+	texureColor = fragTintedColor(texureColor, input.darkColor, input.color, _Color.a, _Black.a);
+#endif
+
 	fixed4 pixel = calculatePixel(texureColor, input.color);
 
 	COLORISE(pixel)

+ 19 - 2
spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/CGIncludes/SpriteVertexLighting.cginc

@@ -4,6 +4,12 @@
 #include "ShaderShared.cginc"
 #include "SpriteLighting.cginc"
 #include "SpriteSpecular.cginc"
+#if defined(_ALPHAPREMULTIPLY_ON)
+	#undef _STRAIGHT_ALPHA_INPUT
+#else
+	#define _STRAIGHT_ALPHA_INPUT
+#endif
+#include "../../CGIncludes/Spine-Skeleton-Tint-Common.cginc"
 
 ////////////////////////////////////////
 // Defines
@@ -115,6 +121,10 @@ struct VertexOutput
 	UNITY_FOG_COORDS(_FOG_COORD_INDEX)
 #endif // _FOG
 
+#if defined(_TINT_BLACK_ON)
+	float3 darkColor : TEXCOORD9;
+#endif
+
 	UNITY_VERTEX_OUTPUT_STEREO
 };
 
@@ -342,9 +352,12 @@ VertexOutput vert(VertexInput input)
 
 	output.pos = calculateLocalPos(input.vertex);
 	output.color = calculateVertexColor(input.color);
+#if defined(_TINT_BLACK_ON)
+	output.darkColor = GammaToTargetSpace(half3(input.tintBlackRG.r, input.tintBlackRG.g, input.tintBlackB.r)) + _Black.rgb;
+#endif
 	output.texcoord = float3(calculateTextureCoord(input.texcoord), 0);
 
-	float3 viewPos = UnityObjectToViewPos(input.vertex);  //float3 viewPos = mul(UNITY_MATRIX_MV, input.vertex); //
+	float3 viewPos = UnityObjectToViewPos(input.vertex);
 #if defined(FIXED_NORMALS_BACKFACE_RENDERING) || defined(_RIM_LIGHTING)
 	float4 powWorld = calculateWorldPos(input.vertex);
 #endif
@@ -402,9 +415,13 @@ VertexOutput vert(VertexInput input)
 fixed4 frag(VertexOutput input) : SV_Target
 {
 	fixed4 texureColor = calculateTexturePixel(input.texcoord.xy);
-	RETURN_UNLIT_IF_ADDITIVE_SLOT(texureColor, input.color) // shall be called before ALPHA_CLIP
+	RETURN_UNLIT_IF_ADDITIVE_SLOT_TINT(texureColor, input.color, input.darkColor, _Color.a, _Black.a) // shall be called before ALPHA_CLIP
 	ALPHA_CLIP(texureColor, input.color)
 
+#if defined(_TINT_BLACK_ON)
+	texureColor = fragTintedColor(texureColor, input.darkColor, input.color, _Color.a, _Black.a);
+#endif
+
 #if defined(PER_PIXEL_LIGHTING)
 
 	#if defined(_NORMALMAP)

+ 3 - 0
spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/SpritesPixelLit.shader

@@ -38,6 +38,8 @@ Shader "Spine/Sprite/Pixel Lit"
 		_BlendAmount ("Blend", Range(0,1)) = 0.0
 
 		[MaterialToggle(_LIGHT_AFFECTS_ADDITIVE)] _LightAffectsAdditive("Light Affects Additive", Float) = 0
+		[MaterialToggle(_TINT_BLACK_ON)]  _TintBlack("Tint Black", Float) = 0
+		_Black("Dark Color", Color) = (0,0,0,0)
 
 		[HideInInspector] _SrcBlend ("__src", Float) = 1.0
 		[HideInInspector] _DstBlend ("__dst", Float) = 0.0
@@ -95,6 +97,7 @@ Shader "Spine/Sprite/Pixel Lit"
 				#pragma shader_feature _SPHERICAL_HARMONICS
 				#pragma shader_feature _FOG
 				#pragma shader_feature _LIGHT_AFFECTS_ADDITIVE
+				#pragma shader_feature _TINT_BLACK_ON
 
 				#pragma multi_compile_fwdbase
 				#pragma fragmentoption ARB_precision_hint_fastest

+ 4 - 0
spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/SpritesUnlit.shader

@@ -20,6 +20,9 @@ Shader "Spine/Sprite/Unlit"
 		_BlendTex ("Blend Texture", 2D) = "white" {}
 		_BlendAmount ("Blend", Range(0,1)) = 0.0
 
+		[MaterialToggle(_TINT_BLACK_ON)]  _TintBlack("Tint Black", Float) = 0
+		_Black("Dark Color", Color) = (0,0,0,0)
+
 		[HideInInspector] _SrcBlend ("__src", Float) = 1.0
 		[HideInInspector] _DstBlend ("__dst", Float) = 0.0
 		[HideInInspector] _RenderQueue ("__queue", Float) = 0.0
@@ -66,6 +69,7 @@ Shader "Spine/Sprite/Unlit"
 				#pragma shader_feature _TEXTURE_BLEND
 				#pragma shader_feature _COLOR_ADJUST
 				#pragma shader_feature _FOG
+				#pragma shader_feature _TINT_BLACK_ON
 
 				#pragma fragmentoption ARB_precision_hint_fastest
 				#pragma multi_compile_fog

+ 3 - 0
spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Sprite/SpritesVertexLit.shader

@@ -39,6 +39,8 @@ Shader "Spine/Sprite/Vertex Lit"
 		_BlendAmount ("Blend", Range(0,1)) = 0.0
 
 		[MaterialToggle(_LIGHT_AFFECTS_ADDITIVE)] _LightAffectsAdditive("Light Affects Additive", Float) = 0
+		[MaterialToggle(_TINT_BLACK_ON)]  _TintBlack("Tint Black", Float) = 0
+		_Black("Dark Color", Color) = (0,0,0,0)
 
 		[HideInInspector] _SrcBlend ("__src", Float) = 1.0
 		[HideInInspector] _DstBlend ("__dst", Float) = 0.0
@@ -96,6 +98,7 @@ Shader "Spine/Sprite/Vertex Lit"
 				#pragma shader_feature _SPHERICAL_HARMONICS
 				#pragma shader_feature _FOG
 				#pragma shader_feature _LIGHT_AFFECTS_ADDITIVE
+				#pragma shader_feature _TINT_BLACK_ON
 
 				#pragma fragmentoption ARB_precision_hint_fastest
 				#pragma multi_compile_fog

+ 1 - 1
spine-unity/Assets/Spine/package.json

@@ -2,7 +2,7 @@
 	"name": "com.esotericsoftware.spine.spine-unity",
 	"displayName": "spine-unity Runtime",
 	"description": "This plugin provides the spine-unity runtime core.",
-	"version": "4.1.11",
+	"version": "4.1.12",
 	"unity": "2018.3",
 	"author": {
 		"name": "Esoteric Software",

+ 20 - 1
spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/2D/Include/Spine-Sprite-StandardPass-URP-2D.hlsl

@@ -5,6 +5,12 @@
 
 #include "../Include/SpineCoreShaders/ShaderShared.cginc"
 #include "../Include/SpineCoreShaders/SpriteLighting.cginc"
+#if defined(_ALPHAPREMULTIPLY_ON)
+	#undef _STRAIGHT_ALPHA_INPUT
+#else
+	#define _STRAIGHT_ALPHA_INPUT
+#endif
+#include "../Include/SpineCoreShaders/Spine-Skeleton-Tint-Common.cginc"
 
 #if USE_SHAPE_LIGHT_TYPE_0
 SHAPE_LIGHT(0)
@@ -44,6 +50,10 @@ struct VertexOutputSpriteURP2D
 #if defined(_RIM_LIGHTING)
 	float4 positionWS : TEXCOORD8;
 #endif
+
+#if defined(_TINT_BLACK_ON)
+	float3 darkColor : TEXCOORD9;
+#endif
 };
 
 VertexOutputSpriteURP2D CombinedShapeLightVertex(VertexInput input)
@@ -57,6 +67,11 @@ VertexOutputSpriteURP2D CombinedShapeLightVertex(VertexInput input)
 	output.lightingUV = ComputeScreenPos(clipVertex).xy;
 
 	output.vertexColor = calculateVertexColor(input.color);
+#if defined(_TINT_BLACK_ON)
+	output.darkColor = GammaToTargetSpace(
+		half3(input.tintBlackRG.r, input.tintBlackRG.g, input.tintBlackB.r)) + _Black.rgb;
+#endif
+
 	output.texcoord = float3(calculateTextureCoord(input.texcoord), 0);
 
 	float3 positionWS = TransformObjectToWorld(input.vertex.xyz);
@@ -87,9 +102,13 @@ VertexOutputSpriteURP2D CombinedShapeLightVertex(VertexInput input)
 half4 CombinedShapeLightFragment(VertexOutputSpriteURP2D input) : SV_Target
 {
 	fixed4 texureColor = calculateTexturePixel(input.texcoord.xy);
-	RETURN_UNLIT_IF_ADDITIVE_SLOT(texureColor, input.vertexColor) // shall be called before ALPHA_CLIP
+	RETURN_UNLIT_IF_ADDITIVE_SLOT_TINT(texureColor, input.vertexColor, input.darkColor, _Color.a, _Black.a) // shall be called before ALPHA_CLIP
 	ALPHA_CLIP(texureColor, input.vertexColor)
+#if defined(_TINT_BLACK_ON)
+	half4 main = fragTintedColor(texureColor, input.darkColor, input.vertexColor, _Color.a, _Black.a);
+#else
 	half4 main = texureColor * input.vertexColor;
+#endif
 
 	half4 mask = SAMPLE_TEXTURE2D(_MaskTex, sampler_MaskTex, input.texcoord.xy);
 	main.rgb = main.a == 0 ? main.rgb : main.rgb / main.a; // un-premultiply for additive lights in CombinedShapeLightShared, reapply afterwards

+ 4 - 0
spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/2D/Spine-Skeleton-URP-2D.shader

@@ -3,6 +3,9 @@ Shader "Universal Render Pipeline/2D/Spine/Skeleton" {
 		_Cutoff("Shadow alpha cutoff", Range(0,1)) = 0.1
 		[NoScaleOffset] _MainTex("Main Texture", 2D) = "black" {}
 		[Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0
+		[MaterialToggle(_TINT_BLACK_ON)]  _TintBlack("Tint Black", Float) = 0
+		_Color("    Light Color", Color) = (1,1,1,1)
+		_Black("    Dark Color", Color) = (0,0,0,0)
 		[HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0
 		[Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Comparison", Float) = 8 // Set to Always as default
 	}
@@ -45,6 +48,7 @@ Shader "Universal Render Pipeline/2D/Spine/Skeleton" {
 			//--------------------------------------
 			// Spine related keywords
 			#pragma shader_feature _ _STRAIGHT_ALPHA_INPUT
+			#pragma shader_feature _TINT_BLACK_ON
 			#pragma vertex vert
 			#pragma fragment frag
 

+ 44 - 5
spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/2D/Spine-SkeletonLit-URP-2D.shader

@@ -1,9 +1,12 @@
-Shader "Universal Render Pipeline/2D/Spine/Skeleton Lit" {
+Shader "Universal Render Pipeline/2D/Spine/Skeleton Lit" {
 	Properties {
 		[NoScaleOffset] _MainTex ("Main Texture", 2D) = "black" {}
 		[NoScaleOffset] _MaskTex("Mask", 2D) = "white" {}
 		[Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0
 		[MaterialToggle(_LIGHT_AFFECTS_ADDITIVE)] _LightAffectsAdditive("Light Affects Additive", Float) = 0
+		[MaterialToggle(_TINT_BLACK_ON)]  _TintBlack("Tint Black", Float) = 0
+		_Color("    Light Color", Color) = (1,1,1,1)
+		_Black("    Dark Color", Color) = (0,0,0,0)
 		[HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0
 		[Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Compare", Float) = 8 // Set to Always as default
 	}
@@ -41,11 +44,16 @@
 			#pragma multi_compile USE_SHAPE_LIGHT_TYPE_2 __
 			#pragma multi_compile USE_SHAPE_LIGHT_TYPE_3 __
 			#pragma multi_compile _ _LIGHT_AFFECTS_ADDITIVE
+			#pragma shader_feature _TINT_BLACK_ON
 
 			struct Attributes {
 				float3 positionOS : POSITION;
 				half4 color : COLOR;
 				float2 uv : TEXCOORD0;
+			#if defined(_TINT_BLACK_ON)
+				float2 tintBlackRG : TEXCOORD1;
+				float2 tintBlackB : TEXCOORD2;
+			#endif
 			};
 
 			struct Varyings {
@@ -53,6 +61,9 @@
 				half4 color : COLOR0;
 				float2 uv : TEXCOORD0;
 				float2 lightingUV : TEXCOORD1;
+			#if defined(_TINT_BLACK_ON)
+				float3 darkColor : TEXCOORD2;
+			#endif
 			};
 
 			// Spine related keywords
@@ -63,6 +74,14 @@
 			#include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/LightingUtility.hlsl"
 			#define USE_URP
 			#include "../Include/SpineCoreShaders/Spine-Common.cginc"
+			#include "../Include/SpineCoreShaders/Spine-Skeleton-Tint-Common.cginc"
+
+		#if defined(_TINT_BLACK_ON)
+			CBUFFER_START(UnityPerMaterial)
+			half4 _Color;
+			half4 _Black;
+			CBUFFER_END
+		#endif
 
 			TEXTURE2D(_MainTex);
 			SAMPLER(sampler_MainTex);
@@ -94,8 +113,16 @@
 				float4 clipVertex = o.positionCS / o.positionCS.w;
 				o.lightingUV = ComputeScreenPos(clipVertex).xy;
 				o.color = PMAGammaToTargetSpace(v.color);
+			#if !defined(_TINT_BLACK_ON)
 				// un-premultiply for additive lights in CombinedShapeLightShared, reapply afterwards
 				o.color.rgb = o.color.a == 0 ? o.color.rgb : o.color.rgb / o.color.a;
+			#endif
+
+			#if defined(_TINT_BLACK_ON)
+				o.color *= _Color;
+				o.darkColor = GammaToTargetSpace(
+					half3(v.tintBlackRG.r, v.tintBlackRG.g, v.tintBlackB.r)) + _Black.rgb;
+			#endif
 				return o;
 			}
 
@@ -104,16 +131,28 @@
 			half4 CombinedShapeLightFragment(Varyings i) : SV_Target
 			{
 				half4 tex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
-			#if !defined(_STRAIGHT_ALPHA_INPUT)
+
+			#if defined(_TINT_BLACK_ON)
+				half4 main = fragTintedColor(tex, i.darkColor, i.color, _Color.a, _Black.a);
+				#if !defined(_LIGHT_AFFECTS_ADDITIVE)
+				if (i.color.a == 0)
+					return main;
+				#endif
+				// un-premultiply for additive lights in CombinedShapeLightShared, reapply afterwards
+				main.rgb = main.a == 0 ? main.rgb : main.rgb / main.a;
+			#else
+				#if !defined(_STRAIGHT_ALPHA_INPUT)
 				// un-premultiply for additive lights in CombinedShapeLightShared, reapply afterwards
 				tex.rgb = tex.a == 0 ? tex.rgb : tex.rgb / tex.a;
-			#endif
-
+				#endif
 				half4 main = tex * i.color;
-			#if !defined(_LIGHT_AFFECTS_ADDITIVE)
+
+				#if !defined(_LIGHT_AFFECTS_ADDITIVE)
 				if (i.color.a == 0)
 					return half4(main.rgb * main.a, main.a);
+				#endif
 			#endif
+
 				half4 mask = SAMPLE_TEXTURE2D(_MaskTex, sampler_MaskTex, i.uv);
 			#if UNITY_VERSION  < 202120
 				return half4(CombinedShapeLightShared(half4(main.rgb, 1), mask, i.lightingUV).rgb * main.a, main.a);

+ 3 - 0
spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/2D/Spine-Sprite-URP-2D.shader

@@ -33,6 +33,8 @@ Shader "Universal Render Pipeline/2D/Spine/Sprite"
 		_BlendAmount("Blend", Range(0,1)) = 0.0
 
 		[MaterialToggle(_LIGHT_AFFECTS_ADDITIVE)] _LightAffectsAdditive("Light Affects Additive", Float) = 0
+		[MaterialToggle(_TINT_BLACK_ON)]  _TintBlack("Tint Black", Float) = 0
+		_Black("Dark Color", Color) = (0,0,0,0)
 
 		[HideInInspector] _SrcBlend("__src", Float) = 1.0
 		[HideInInspector] _DstBlend("__dst", Float) = 0.0
@@ -85,6 +87,7 @@ Shader "Universal Render Pipeline/2D/Spine/Sprite"
 			#pragma shader_feature _RIM_LIGHTING
 			#pragma shader_feature _TEXTURE_BLEND
 			#pragma shader_feature _LIGHT_AFFECTS_ADDITIVE
+			#pragma shader_feature _TINT_BLACK_ON
 
 			#pragma fragmentoption ARB_precision_hint_fastest
 			#pragma multi_compile _ PIXELSNAP_ON

+ 3 - 0
spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Include/Spine-Input-Sprite-URP.hlsl

@@ -7,6 +7,9 @@ CBUFFER_START(UnityPerMaterial)
 
 float4 _MainTex_ST;
 half4 _Color;
+#if defined(_TINT_BLACK_ON)
+half4 _Black;
+#endif
 half _Cutoff;
 half _ShadowAlphaCutoff;
 

+ 6 - 0
spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Include/Spine-Input-URP.hlsl

@@ -9,8 +9,14 @@
 #undef LIGHTMAP_ON
 
 CBUFFER_START(UnityPerMaterial)
+
 float4 _MainTex_ST;
 half _Cutoff;
+#if defined(_TINT_BLACK_ON)
+    half4 _Color;
+    half4 _Black;
+#endif
+
 CBUFFER_END
 
 sampler2D _MainTex;

+ 17 - 2
spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Include/Spine-Skeleton-ForwardPass-URP.hlsl

@@ -4,11 +4,16 @@
 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
 #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
 #include "SpineCoreShaders/Spine-Common.cginc"
+#include "SpineCoreShaders/Spine-Skeleton-Tint-Common.cginc"
 
 struct appdata {
 	float3 pos : POSITION;
 	half4 color : COLOR;
 	float2 uv0 : TEXCOORD0;
+#if defined(_TINT_BLACK_ON)
+	float2 tintBlackRG : TEXCOORD1;
+	float2 tintBlackB : TEXCOORD2;
+#endif
 
 	UNITY_VERTEX_INPUT_INSTANCE_ID
 };
@@ -17,6 +22,9 @@ struct VertexOutput {
 	half4 color : COLOR0;
 	float2 uv0 : TEXCOORD0;
 	float4 pos : SV_POSITION;
+#if defined(_TINT_BLACK_ON)
+	float3 darkColor : TEXCOORD1;
+#endif
 	UNITY_VERTEX_OUTPUT_STEREO
 };
 
@@ -29,17 +37,24 @@ VertexOutput vert(appdata v) {
 	o.pos = TransformWorldToHClip(positionWS);
 	o.uv0 = v.uv0;
 	o.color = PMAGammaToTargetSpace(v.color);
+#if defined(_TINT_BLACK_ON)
+	o.color *= _Color;
+	o.darkColor = GammaToTargetSpace(
+		half3(v.tintBlackRG.r, v.tintBlackRG.g, v.tintBlackB.r)) + _Black.rgb;
+#endif
 	return o;
 }
 
 half4 frag(VertexOutput i) : SV_Target{
 	float4 texColor = tex2D(_MainTex, i.uv0);
-
+#if defined(_TINT_BLACK_ON)
+	return fragTintedColor(texColor, i.darkColor, i.color, _Color.a, _Black.a);
+#else
 	#if defined(_STRAIGHT_ALPHA_INPUT)
 	texColor.rgb *= texColor.a;
 	#endif
-
 	return (texColor * i.color);
+#endif
 }
 
 #endif

+ 28 - 7
spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Include/Spine-SkeletonLit-ForwardPass-URP.hlsl

@@ -1,4 +1,4 @@
-#ifndef SKELETONLIT_FORWARD_PASS_URP_INCLUDED
+#ifndef SKELETONLIT_FORWARD_PASS_URP_INCLUDED
 #define SKELETONLIT_FORWARD_PASS_URP_INCLUDED
 
 #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
@@ -6,6 +6,7 @@
 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
 #include "SpineCoreShaders/Spine-Common.cginc"
 #include "Spine-Common-URP.hlsl"
+#include "SpineCoreShaders/Spine-Skeleton-Tint-Common.cginc"
 
 #if (defined(_MAIN_LIGHT_SHADOWS) || defined(MAIN_LIGHT_CALCULATE_SHADOWS)) && !defined(_RECEIVE_SHADOWS_OFF)
 #define SKELETONLIT_RECEIVE_SHADOWS
@@ -16,7 +17,10 @@ struct appdata {
 	float3 normal : NORMAL;
 	half4 color : COLOR;
 	float2 uv0 : TEXCOORD0;
-
+#if defined(_TINT_BLACK_ON)
+	float2 tintBlackRG : TEXCOORD1;
+	float2 tintBlackB : TEXCOORD2;
+#endif
 	UNITY_VERTEX_INPUT_INSTANCE_ID
 };
 
@@ -33,7 +37,9 @@ struct VertexOutput {
 	float3 positionWS : TEXCOORD3;
 	half3 normalWS : TEXCOORD4;
 #endif
-
+#if defined(_TINT_BLACK_ON)
+	float3 darkColor : TEXCOORD5;
+#endif
 	UNITY_VERTEX_OUTPUT_STEREO
 };
 
@@ -119,6 +125,12 @@ VertexOutput vert(appdata v) {
 	o.normalWS = normalWS;
 #endif
 
+#if defined(_TINT_BLACK_ON)
+	color *= _Color;
+	o.darkColor = GammaToTargetSpace(
+		half3(v.tintBlackRG.r, v.tintBlackRG.g, v.tintBlackB.r)) + _Black.rgb;
+#endif
+
 	half3 shadowedColor;
 #if !defined(_LIGHT_AFFECTS_ADDITIVE)
 	if (color.a == 0) {
@@ -139,7 +151,7 @@ VertexOutput vert(appdata v) {
 	// Note: ambient light is also handled via SH.
 	half3 vertexSH;
 	OUTPUT_SH(normalWS.xyz, vertexSH);
-	color.rgb += SAMPLE_GI(input.lightmapUV, vertexSH, normalWS);
+	color.rgb += SAMPLE_GI(v.lightmapUV, vertexSH, normalWS);
 	o.color = color;
 
 #if defined(SKELETONLIT_RECEIVE_SHADOWS)
@@ -158,12 +170,17 @@ half4 frag(VertexOutput i
 ) : SV_Target0
 {
 	half4 tex = tex2D(_MainTex, i.uv0);
-	#if defined(_STRAIGHT_ALPHA_INPUT)
+#if !defined(_TINT_BLACK_ON) && defined(_STRAIGHT_ALPHA_INPUT)
 	tex.rgb *= tex.a;
-	#endif
+#endif
 
-	if (i.color.a == 0)
+	if (i.color.a == 0)	{
+#if defined(_TINT_BLACK_ON)
+		return fragTintedColor(tex, i.darkColor, i.color, _Color.a, _Black.a);
+#else
 		return tex * i.color;
+#endif
+	}
 
 #if defined(_ADDITIONAL_LIGHTS) && USE_FORWARD_PLUS
 	// USE_FORWARD_PLUS lights need to be processed in fragment shader,
@@ -185,7 +202,11 @@ half4 frag(VertexOutput i
 	outRenderingLayers = float4(EncodeMeshRenderingLayer(renderingLayers), 0, 0, 0);
 #endif
 
+#if defined(_TINT_BLACK_ON)
+	return fragTintedColor(tex, i.darkColor, i.color, _Color.a, _Black.a);
+#else
 	return tex * i.color;
+#endif
 }
 
 #endif

+ 29 - 1
spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Include/Spine-Sprite-ForwardPass-URP.hlsl

@@ -7,6 +7,13 @@
 #include "SpineCoreShaders/Spine-Common.cginc"
 #include "Spine-Common-URP.hlsl"
 
+#if defined(_ALPHAPREMULTIPLY_ON)
+	#undef _STRAIGHT_ALPHA_INPUT
+#else
+	#define _STRAIGHT_ALPHA_INPUT
+#endif
+#include "SpineCoreShaders/Spine-Skeleton-Tint-Common.cginc"
+
 #if defined(_RIM_LIGHTING) || defined(_ADDITIONAL_LIGHTS) || defined(MAIN_LIGHT_CALCULATE_SHADOWS) || defined(_LIGHT_COOKIES)
 	#define NEEDS_POSITION_WS
 #endif
@@ -38,6 +45,9 @@ struct VertexOutputLWRP
 #if defined(NEEDS_POSITION_WS)
 	float4 positionWS : TEXCOORD8;
 #endif
+#if defined(_TINT_BLACK_ON)
+	float3 darkColor : TEXCOORD9;
+#endif
 
 	UNITY_VERTEX_OUTPUT_STEREO
 };
@@ -109,7 +119,11 @@ half3 ProcessLightPBRSimplified(InputData inputData, BRDFData brdfData, half4 sh
 half4 LightweightFragmentPBRSimplified(InputData inputData, half4 texAlbedoAlpha, half metallic, half3 specular,
 	half smoothness, half3 emission, half4 vertexColor)
 {
+#if !defined(_TINT_BLACK_ON)
 	half4 albedo = texAlbedoAlpha * vertexColor;
+#else
+	half4 albedo = texAlbedoAlpha;
+#endif
 
 	BRDFData brdfData;
 	half ignoredAlpha = 1; // ignore alpha, otherwise
@@ -189,7 +203,11 @@ half3 ProcessLightLambert(InputData inputData, half4 shadowMask, uint meshRender
 
 half4 LightweightFragmentBlinnPhongSimplified(InputData inputData, half4 texDiffuseAlpha, half3 emission, half4 vertexColor)
 {
+#if !defined(_TINT_BLACK_ON)
 	half4 diffuse = texDiffuseAlpha * vertexColor;
+#else
+	half4 diffuse = texDiffuseAlpha;
+#endif
 
 #ifndef _MAIN_LIGHT_VERTEX
 #if (defined(_MAIN_LIGHT_SHADOWS) || defined(MAIN_LIGHT_CALCULATE_SHADOWS)) && !defined(_RECEIVE_SHADOWS_OFF)
@@ -255,6 +273,10 @@ VertexOutputLWRP ForwardPassVertexSprite(VertexInput input)
 
 	output.pos = calculateLocalPos(input.vertex);
 	output.vertexColor = calculateVertexColor(input.color);
+#if defined(_TINT_BLACK_ON)
+	output.darkColor = GammaToTargetSpace(
+		half3(input.tintBlackRG.r, input.tintBlackRG.g, input.tintBlackB.r)) + _Black.rgb;
+#endif
 	output.texcoord = float3(calculateTextureCoord(input.texcoord), 0);
 
 	float3 positionWS = TransformObjectToWorld(input.vertex.xyz);
@@ -302,9 +324,15 @@ half4 ForwardPassFragmentSprite(VertexOutputLWRP input
 	UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
 
 	fixed4 texureColor = calculateTexturePixel(input.texcoord.xy);
-	RETURN_UNLIT_IF_ADDITIVE_SLOT(texureColor, input.vertexColor) // shall be called before ALPHA_CLIP
+
+	RETURN_UNLIT_IF_ADDITIVE_SLOT_TINT(texureColor, input.vertexColor, input.darkColor, _Color.a, _Black.a) // shall be called before ALPHA_CLIP
+
 	ALPHA_CLIP(texureColor, input.vertexColor)
 
+#if defined(_TINT_BLACK_ON)
+	texureColor = fragTintedColor(texureColor, input.darkColor, input.vertexColor, _Color.a, _Black.a);
+#endif
+
 	// fill out InputData struct
 	InputData inputData;
 #if !defined(_RECEIVE_SHADOWS_OFF)

+ 3 - 0
spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Include/SpineCoreShaders/Spine-Skeleton-Tint-Common.cginc

@@ -0,0 +1,3 @@
+// Adapt this path accordingly if you have unpacked the Spine directory to another location.
+//#include "Assets/Spine/Runtime/spine-unity/Shaders/CGIncludes/Spine-Skeleton-Tint-Common.cginc"
+#include "Packages/com.esotericsoftware.spine.spine-unity/Runtime/spine-unity/Shaders/CGIncludes/Spine-Skeleton-Tint-Common.cginc"

+ 10 - 0
spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Include/SpineCoreShaders/Spine-Skeleton-Tint-Common.cginc.meta

@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 17717bcd66ca5ee4388ec779392904c3
+ShaderImporter:
+  externalObjects: {}
+  defaultTextures: []
+  nonModifiableTextures: []
+  preprocessorOverride: 0
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 4 - 0
spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Spine-Skeleton-URP.shader

@@ -3,6 +3,9 @@ Shader "Universal Render Pipeline/Spine/Skeleton" {
 		_Cutoff("Shadow alpha cutoff", Range(0,1)) = 0.1
 		[NoScaleOffset] _MainTex("Main Texture", 2D) = "black" {}
 		[Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0
+		[MaterialToggle(_TINT_BLACK_ON)]  _TintBlack("Tint Black", Float) = 0
+		_Color("    Light Color", Color) = (1,1,1,1)
+		_Black("    Dark Color", Color) = (0,0,0,0)
 		[HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0
 		[Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Comparison", Float) = 8 // Set to Always as default
 	}
@@ -46,6 +49,7 @@ Shader "Universal Render Pipeline/Spine/Skeleton" {
 			//--------------------------------------
 			// Spine related keywords
 			#pragma shader_feature _ _STRAIGHT_ALPHA_INPUT
+			#pragma shader_feature _TINT_BLACK_ON
 			#pragma vertex vert
 			#pragma fragment frag
 

+ 4 - 0
spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Spine-SkeletonLit-URP.shader

@@ -6,6 +6,9 @@
 		[Toggle(_RECEIVE_SHADOWS)] _ReceiveShadows("Receive Shadows", Int) = 0
 		[Toggle(_DOUBLE_SIDED_LIGHTING)] _DoubleSidedLighting("Double-Sided Lighting", Int) = 0
 		[MaterialToggle(_LIGHT_AFFECTS_ADDITIVE)] _LightAffectsAdditive("Light Affects Additive", Float) = 0
+		[MaterialToggle(_TINT_BLACK_ON)]  _TintBlack("Tint Black", Float) = 0
+		_Color("    Light Color", Color) = (1,1,1,1)
+		_Black("    Dark Color", Color) = (0,0,0,0)
 		[HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0
 		[Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Compare", Float) = 8 // Set to Always as default
 	}
@@ -47,6 +50,7 @@
 			#pragma multi_compile _ _SHADOWS_SOFT
 			#pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE
 			#pragma multi_compile _ _LIGHT_AFFECTS_ADDITIVE
+			#pragma shader_feature _TINT_BLACK_ON
 			// Farward+ renderer keywords
 			#pragma multi_compile_fragment _ _LIGHT_LAYERS
 			#pragma multi_compile _ _FORWARD_PLUS

+ 3 - 0
spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Spine-Sprite-URP.shader

@@ -39,6 +39,8 @@ Shader "Universal Render Pipeline/Spine/Sprite"
 		_BlendAmount("Blend", Range(0,1)) = 0.0
 
 		[MaterialToggle(_LIGHT_AFFECTS_ADDITIVE)] _LightAffectsAdditive("Light Affects Additive", Float) = 0
+		[MaterialToggle(_TINT_BLACK_ON)]  _TintBlack("Tint Black", Float) = 0
+		_Black("Dark Color", Color) = (0,0,0,0)
 
 		[HideInInspector] _SrcBlend("__src", Float) = 1.0
 		[HideInInspector] _DstBlend("__dst", Float) = 0.0
@@ -95,6 +97,7 @@ Shader "Universal Render Pipeline/Spine/Sprite"
 			#pragma shader_feature _FOG
 			#pragma shader_feature _RECEIVE_SHADOWS_OFF
 			#pragma shader_feature _LIGHT_AFFECTS_ADDITIVE
+			#pragma shader_feature _TINT_BLACK_ON
 
 			#pragma fragmentoption ARB_precision_hint_fastest
 			#pragma multi_compile_fog

+ 1 - 1
spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/package.json

@@ -2,7 +2,7 @@
   "name": "com.esotericsoftware.spine.urp-shaders",
   "displayName": "Spine Universal RP Shaders",
   "description": "This plugin provides universal render pipeline (URP) shaders for the spine-unity runtime.\n\nPrerequisites:\nIt requires a working installation of the spine-unity runtime, version 4.1.\n(See http://esotericsoftware.com/git/spine-runtimes/spine-unity)",
-  "version": "4.1.13",
+  "version": "4.1.14",
   "unity": "2019.3",
   "author": {
     "name": "Esoteric Software",