- Изменено
Add Soft Mask support to Spine Shader
I'm trying to add Soft Mask support to our Spine Shader.
Here's the documentation for adding Soft Mask support to shaders:
https://docs.google.com/document/d/1mFEml0JWhR968GG1gVBBTLsJ8ubf_oraW5MBbrvkrb0/edit
Here's our Spine Shader with the Soft Mask additions:
// This is a premultiply-alpha adaptation of the built-in Unity shader "UI/Default" in Unity 5.6.2 to allow Unity UI stencil masking.
Shader "Spine/SkeletonGraphic SoftMask (Premultiply Alpha)"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
_StencilComp ("Stencil Comparison", Float) = 8
_Stencil ("Stencil ID", Float) = 0
_StencilOp ("Stencil Operation", Float) = 0
_StencilWriteMask ("Stencil Write Mask", Float) = 255
_StencilReadMask ("Stencil Read Mask", Float) = 255
_ColorMask ("Color Mask", Float) = 15
_SoftMask ("Mask", 2D) = "white" {}
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
}
SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
Stencil
{
Ref [_Stencil]
Comp [_StencilComp]
Pass [_StencilOp]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}
Cull Off
Lighting Off
ZWrite Off
ZTest [unity_GUIZTestMode]
Fog { Mode Off }
Blend One OneMinusSrcAlpha
ColorMask [_ColorMask]
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#include "UnityCG.cginc"
#include "UnityUI.cginc"
#include "Assets/ThirdParty/SoftMask/Shaders/SoftMask.cginc"
#pragma multi_compile __ UNITY_UI_ALPHACLIP
#pragma multi_compile __ SOFTMASK_SIMPLE SOFTMASK_SLICED SOFTMASK_TILED
struct VertexInput {
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct VertexOutput {
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
half2 texcoord : TEXCOORD0;
float4 worldPosition : TEXCOORD1;
SOFTMASK_COORDS(2)
UNITY_VERTEX_OUTPUT_STEREO
};
fixed4 _Color;
fixed4 _TextureSampleAdd;
float4 _ClipRect;
VertexOutput vert (VertexInput IN) {
VertexOutput OUT;
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.worldPosition = IN.vertex;
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
OUT.texcoord = IN.texcoord;
#ifdef UNITY_HALF_TEXEL_OFFSET
OUT.vertex.xy += (_ScreenParams.zw-1.0) * float2(-1,1);
#endif
OUT.color = IN.color * _Color;
SOFTMASK_CALCULATE_COORDS(OUT, IN.vertex);
return OUT;
}
sampler2D _MainTex;
fixed4 frag (VertexOutput IN) : SV_Target
{
half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect) * SOFTMASK_GET_MASK(IN);
#ifdef UNITY_UI_ALPHACLIP
clip (color.a - 0.001);
#endif
return color;
}
ENDCG
}
}
}
Please see the attached image for the current results. The semi-transparent parts outside the rounded rectangle are supposed to be fully transparent.
I've seen this unwanted additive symptom related to transparency when adjusting a parent Canvas Group, which is well detailed in the following thread:
http://en.esotericsoftware.com/forum/CanvasGroup-s-alpha-does-not-affect-SkeletonGraphic-9467
I feel like this could be related? The final reply in that thread shows a CanvasGroup Compatible setting in the latest Spine, so it appears there could be a shader fix. I'm hoping we can apply that fix to the shader above, as we are currently running a pretty old version of Spine (3.6.x.x). We hope to update this soon.
Anyway, any help getting Soft Mask to work with our Spine Shader would be greatly appreciated!
Spine shaders always use Premultiplied Alpha
(PMA) blending on the output. So you need to not only multiply color.a
by the mask value but also color.rgb
.
color.a *= SOFTMASK_GET_MASK(IN); // this is not sufficient, rgb values need adjustment
color *= SOFTMASK_GET_MASK(IN); // this is correct
Ahh, that makes sense. Works great! Thanks for the quick reply!
You're welcome, glad you've figured it out!