diff --git a/CHANGELOG.md b/CHANGELOG.md index 284f0df99..b55c4a1d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -239,6 +239,7 @@ * Added a new `Spine/Outline/OutlineOnly-ZWrite` shader to provide correct outline-only rendering. Note: the shader requires two render passes and is therefore not compatible with URP. The `Spine Examples/Other Examples/Outline Shaders` example scene has been updated to demonstrate the new shader. * Added `OnMeshAndMaterialsUpdated` callback event to `SkeletonRenderSeparator` and `SkeletonPartsRenderer`. It is issued at the end of `LateUpdate`, before rendering. * Added `Root Motion Scale X/Y` parameters to `SkeletonRootMotionBase` subclasses (`SkeletonRootMotion` and `SkeletonMecanimRootMotion`). Also providing `AdjustRootMotionToDistance()` and other methods to allow for easy delta compensation. Delta compensation can be used to e.g. stretch a jump to a given distance. Root motion can be adjusted at the start of an animation or every frame via `skeletonRootMotion.AdjustRootMotionToDistance(targetPosition - transform.position, trackIndex);`. + * Now providing a `Canvas Group Tint Black` parameter a `SkeletonGraphic` Inspector in the `Advanced` section. Enable when using Additive blend mode at SkeletonGraphic under a CanvasGroup. Be sure to also have the parameter `CanvasGroup Compatible` enabled at the shader. * **Changes of default values** * `SkeletonMecanim`'s `Layer Mix Mode` now defaults to `MixMode.MixNext` instead of `MixMode.MixAlways`. diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/MeshGenerator.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/MeshGenerator.cs index 87da59f34..27a2f0eaa 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/MeshGenerator.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/MeshGenerator.cs @@ -68,6 +68,9 @@ namespace Spine.Unity { [Header("Vertex Data")] public bool pmaVertexColors; public bool tintBlack; + [Tooltip("Enable when using Additive blend mode at SkeletonGraphic under a CanvasGroup. " + + "When enabled, Additive alpha value is stored at uv2.g instead of color.a to capture CanvasGroup modifying color.a.")] + public bool canvasGroupTintBlack; public bool calculateTangents; public bool addNormals; public bool immutableTriangles; @@ -493,6 +496,7 @@ namespace Spine.Unity { #else bool useClipping = settings.useClipping; #endif + bool canvasGroupTintBlack = settings.tintBlack && settings.canvasGroupTintBlack; if (useClipping) { if (instruction.preActiveClippingSlotSource >= 0) { @@ -556,12 +560,18 @@ namespace Spine.Unity { } } + float tintBlackAlpha = 1.0f; if (pmaVertexColors) { color.a = (byte)(skeletonA * slot.a * c.a * 255); color.r = (byte)(skeletonR * slot.r * c.r * color.a); color.g = (byte)(skeletonG * slot.g * c.g * color.a); color.b = (byte)(skeletonB * slot.b * c.b * color.a); - if (slot.data.blendMode == BlendMode.Additive) color.a = 0; + if (slot.data.blendMode == BlendMode.Additive) { + if (canvasGroupTintBlack) + tintBlackAlpha = 0; + else + color.a = 0; + } } else { color.a = (byte)(skeletonA * slot.a * c.a * 255); color.r = (byte)(skeletonR * slot.r * c.r * 255); @@ -590,7 +600,7 @@ namespace Spine.Unity { g2 *= alpha; b2 *= alpha; } - AddAttachmentTintBlack(r2, g2, b2, attachmentVertexCount); + AddAttachmentTintBlack(r2, g2, b2, tintBlackAlpha, attachmentVertexCount); } //AddAttachment(workingVerts, uvs, color, attachmentTriangleIndices, attachmentVertexCount, attachmentIndexCount, ref meshBoundsMin, ref meshBoundsMax, z); @@ -694,6 +704,7 @@ namespace Spine.Unity { // Use this faster method when no clipping is involved. public void BuildMeshWithArrays (SkeletonRendererInstruction instruction, bool updateTriangles) { var settings = this.settings; + bool canvasGroupTintBlack = settings.tintBlack && settings.canvasGroupTintBlack; int totalVertexCount = instruction.rawVertexCount; // Add data to vertex buffers @@ -758,6 +769,7 @@ namespace Spine.Unity { rg.x = slot.r2; //r rg.y = slot.g2; //g b2.x = slot.b2; //b + b2.y = 1.0f; var regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { @@ -766,6 +778,7 @@ namespace Spine.Unity { rg.x *= alpha; rg.y *= alpha; b2.x *= alpha; + b2.y = slot.data.blendMode == BlendMode.Additive ? 0 : alpha; } uv2i[vi] = rg; uv2i[vi + 1] = rg; uv2i[vi + 2] = rg; uv2i[vi + 3] = rg; uv3i[vi] = b2; uv3i[vi + 1] = b2; uv3i[vi + 2] = b2; uv3i[vi + 3] = b2; @@ -778,6 +791,7 @@ namespace Spine.Unity { rg.x *= alpha; rg.y *= alpha; b2.x *= alpha; + b2.y = slot.data.blendMode == BlendMode.Additive ? 0 : alpha; } int meshVertexCount = meshAttachment.worldVerticesLength; for (int iii = 0; iii < meshVertexCount; iii += 2) { @@ -814,7 +828,7 @@ namespace Spine.Unity { color.r = (byte)(r * slot.r * regionAttachment.r * color.a); color.g = (byte)(g * slot.g * regionAttachment.g * color.a); color.b = (byte)(b * slot.b * regionAttachment.b * color.a); - if (slot.data.blendMode == BlendMode.Additive) color.a = 0; + if (slot.data.blendMode == BlendMode.Additive && !canvasGroupTintBlack) color.a = 0; } else { color.a = (byte)(a * slot.a * regionAttachment.a * 255); color.r = (byte)(r * slot.r * regionAttachment.r * 255); @@ -861,7 +875,7 @@ namespace Spine.Unity { color.r = (byte)(r * slot.r * meshAttachment.r * color.a); color.g = (byte)(g * slot.g * meshAttachment.g * color.a); color.b = (byte)(b * slot.b * meshAttachment.b * color.a); - if (slot.data.blendMode == BlendMode.Additive) color.a = 0; + if (slot.data.blendMode == BlendMode.Additive && !canvasGroupTintBlack) color.a = 0; } else { color.a = (byte)(a * slot.a * meshAttachment.a * 255); color.r = (byte)(r * slot.r * meshAttachment.r * 255); @@ -985,9 +999,9 @@ namespace Spine.Unity { meshBoundsThickness *= scale; } - void AddAttachmentTintBlack (float r2, float g2, float b2, int vertexCount) { + void AddAttachmentTintBlack (float r2, float g2, float b2, float a, int vertexCount) { var rg = new Vector2(r2, g2); - var bo = new Vector2(b2, 1f); + var bo = new Vector2(b2, a); int ovc = vertexBuffer.Count; int newVertexCount = ovc + vertexCount; diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-TintBlack.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-TintBlack.shader index 9b9524810..16954acac 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-TintBlack.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/SkeletonGraphic/Spine-SkeletonGraphic-TintBlack.shader @@ -89,7 +89,7 @@ Shader "Spine/SkeletonGraphic Tint Black" float4 vertex : SV_POSITION; fixed4 color : COLOR; half2 texcoord : TEXCOORD0; - float3 darkColor : TEXCOORD1; + float4 darkColor : TEXCOORD1; float4 worldPosition : TEXCOORD2; UNITY_VERTEX_OUTPUT_STEREO }; @@ -110,7 +110,7 @@ Shader "Spine/SkeletonGraphic Tint Black" OUT.texcoord = IN.texcoord; OUT.color = IN.color * _Color; - OUT.darkColor = float3(IN.uv1.r, IN.uv1.g, IN.uv2.r); + OUT.darkColor = float4(IN.uv1.r, IN.uv1.g, IN.uv2.r, IN.uv2.g); return OUT; } @@ -125,10 +125,17 @@ Shader "Spine/SkeletonGraphic Tint Black" clip(texColor.a - 0.001); #endif - float4 fragColor = fragTintedColor(texColor, _Black.rgb + IN.darkColor, IN.color, _Black.a); + float4 vertexColor = IN.color; #ifdef _CANVAS_GROUP_COMPATIBLE - // CanvasGroup alpha sets vertex color alpha, but does not premultiply it to rgb components. - fragColor.rgb *= IN.color.a; + // CanvasGroup alpha multiplies existing vertex color alpha, but + // does not premultiply it to rgb components. This causes problems + // with additive blending (alpha = 0), which is why we store the + // alpha value in uv2.g (darkColor.a). + vertexColor.a = IN.darkColor.a; + #endif + float4 fragColor = fragTintedColor(texColor, _Black.rgb + IN.darkColor, vertexColor, _Black.a); + #ifdef _CANVAS_GROUP_COMPATIBLE + fragColor.rgba *= IN.color.a; #endif return fragColor; }