[unity] Fixed enabling CanvasGroup Compatible at Spine-SkeletonGraphic-TintBlack shader causing Additive blend mode not to work but instead hide the attachment completely. Now providing a Canvas Group Tint Black parameter a SkeletonGraphic Inspector in the Advanced section. Closes #1756.

This commit is contained in:
Harald Csaszar 2020-09-11 20:38:14 +02:00
parent 4cf792f51d
commit d43b7b0a9f
3 changed files with 33 additions and 11 deletions

View File

@ -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 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 `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);`. * 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** * **Changes of default values**
* `SkeletonMecanim`'s `Layer Mix Mode` now defaults to `MixMode.MixNext` instead of `MixMode.MixAlways`. * `SkeletonMecanim`'s `Layer Mix Mode` now defaults to `MixMode.MixNext` instead of `MixMode.MixAlways`.

View File

@ -68,6 +68,9 @@ namespace Spine.Unity {
[Header("Vertex Data")] [Header("Vertex Data")]
public bool pmaVertexColors; public bool pmaVertexColors;
public bool tintBlack; 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 calculateTangents;
public bool addNormals; public bool addNormals;
public bool immutableTriangles; public bool immutableTriangles;
@ -493,6 +496,7 @@ namespace Spine.Unity {
#else #else
bool useClipping = settings.useClipping; bool useClipping = settings.useClipping;
#endif #endif
bool canvasGroupTintBlack = settings.tintBlack && settings.canvasGroupTintBlack;
if (useClipping) { if (useClipping) {
if (instruction.preActiveClippingSlotSource >= 0) { if (instruction.preActiveClippingSlotSource >= 0) {
@ -556,12 +560,18 @@ namespace Spine.Unity {
} }
} }
float tintBlackAlpha = 1.0f;
if (pmaVertexColors) { if (pmaVertexColors) {
color.a = (byte)(skeletonA * slot.a * c.a * 255); color.a = (byte)(skeletonA * slot.a * c.a * 255);
color.r = (byte)(skeletonR * slot.r * c.r * color.a); color.r = (byte)(skeletonR * slot.r * c.r * color.a);
color.g = (byte)(skeletonG * slot.g * c.g * color.a); color.g = (byte)(skeletonG * slot.g * c.g * color.a);
color.b = (byte)(skeletonB * slot.b * c.b * 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 { } else {
color.a = (byte)(skeletonA * slot.a * c.a * 255); color.a = (byte)(skeletonA * slot.a * c.a * 255);
color.r = (byte)(skeletonR * slot.r * c.r * 255); color.r = (byte)(skeletonR * slot.r * c.r * 255);
@ -590,7 +600,7 @@ namespace Spine.Unity {
g2 *= alpha; g2 *= alpha;
b2 *= 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); //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. // Use this faster method when no clipping is involved.
public void BuildMeshWithArrays (SkeletonRendererInstruction instruction, bool updateTriangles) { public void BuildMeshWithArrays (SkeletonRendererInstruction instruction, bool updateTriangles) {
var settings = this.settings; var settings = this.settings;
bool canvasGroupTintBlack = settings.tintBlack && settings.canvasGroupTintBlack;
int totalVertexCount = instruction.rawVertexCount; int totalVertexCount = instruction.rawVertexCount;
// Add data to vertex buffers // Add data to vertex buffers
@ -758,6 +769,7 @@ namespace Spine.Unity {
rg.x = slot.r2; //r rg.x = slot.r2; //r
rg.y = slot.g2; //g rg.y = slot.g2; //g
b2.x = slot.b2; //b b2.x = slot.b2; //b
b2.y = 1.0f;
var regionAttachment = attachment as RegionAttachment; var regionAttachment = attachment as RegionAttachment;
if (regionAttachment != null) { if (regionAttachment != null) {
@ -766,6 +778,7 @@ namespace Spine.Unity {
rg.x *= alpha; rg.x *= alpha;
rg.y *= alpha; rg.y *= alpha;
b2.x *= 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; 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; 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.x *= alpha;
rg.y *= alpha; rg.y *= alpha;
b2.x *= alpha; b2.x *= alpha;
b2.y = slot.data.blendMode == BlendMode.Additive ? 0 : alpha;
} }
int meshVertexCount = meshAttachment.worldVerticesLength; int meshVertexCount = meshAttachment.worldVerticesLength;
for (int iii = 0; iii < meshVertexCount; iii += 2) { 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.r = (byte)(r * slot.r * regionAttachment.r * color.a);
color.g = (byte)(g * slot.g * regionAttachment.g * color.a); color.g = (byte)(g * slot.g * regionAttachment.g * color.a);
color.b = (byte)(b * slot.b * regionAttachment.b * 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 { } else {
color.a = (byte)(a * slot.a * regionAttachment.a * 255); color.a = (byte)(a * slot.a * regionAttachment.a * 255);
color.r = (byte)(r * slot.r * regionAttachment.r * 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.r = (byte)(r * slot.r * meshAttachment.r * color.a);
color.g = (byte)(g * slot.g * meshAttachment.g * color.a); color.g = (byte)(g * slot.g * meshAttachment.g * color.a);
color.b = (byte)(b * slot.b * meshAttachment.b * 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 { } else {
color.a = (byte)(a * slot.a * meshAttachment.a * 255); color.a = (byte)(a * slot.a * meshAttachment.a * 255);
color.r = (byte)(r * slot.r * meshAttachment.r * 255); color.r = (byte)(r * slot.r * meshAttachment.r * 255);
@ -985,9 +999,9 @@ namespace Spine.Unity {
meshBoundsThickness *= scale; 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 rg = new Vector2(r2, g2);
var bo = new Vector2(b2, 1f); var bo = new Vector2(b2, a);
int ovc = vertexBuffer.Count; int ovc = vertexBuffer.Count;
int newVertexCount = ovc + vertexCount; int newVertexCount = ovc + vertexCount;

View File

@ -89,7 +89,7 @@ Shader "Spine/SkeletonGraphic Tint Black"
float4 vertex : SV_POSITION; float4 vertex : SV_POSITION;
fixed4 color : COLOR; fixed4 color : COLOR;
half2 texcoord : TEXCOORD0; half2 texcoord : TEXCOORD0;
float3 darkColor : TEXCOORD1; float4 darkColor : TEXCOORD1;
float4 worldPosition : TEXCOORD2; float4 worldPosition : TEXCOORD2;
UNITY_VERTEX_OUTPUT_STEREO UNITY_VERTEX_OUTPUT_STEREO
}; };
@ -110,7 +110,7 @@ Shader "Spine/SkeletonGraphic Tint Black"
OUT.texcoord = IN.texcoord; OUT.texcoord = IN.texcoord;
OUT.color = IN.color * _Color; 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; return OUT;
} }
@ -125,10 +125,17 @@ Shader "Spine/SkeletonGraphic Tint Black"
clip(texColor.a - 0.001); clip(texColor.a - 0.001);
#endif #endif
float4 fragColor = fragTintedColor(texColor, _Black.rgb + IN.darkColor, IN.color, _Black.a); float4 vertexColor = IN.color;
#ifdef _CANVAS_GROUP_COMPATIBLE #ifdef _CANVAS_GROUP_COMPATIBLE
// CanvasGroup alpha sets vertex color alpha, but does not premultiply it to rgb components. // CanvasGroup alpha multiplies existing vertex color alpha, but
fragColor.rgb *= IN.color.a; // 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 #endif
return fragColor; return fragColor;
} }