Greetings,
When I was profiling our game I noticed that our masks were quite big and thus resulting to overdraw not to mention breaking batching.
Masking in our game is quite simple, we have a water surface and anything below it should be hidden.
I've made the following shader, which works for our needs.
Shader "Spine/Skeleton-Clip" {
Properties{
_Cutoff("Shadow alpha cutoff", Range(0,1)) = 0.1
_WaterSurface("Water surface", Float) = 0.1
_MaskHeight("Mask height", Float) = 0.1
_MaskWidth("Mask width", Float) = 0.5
[NoScaleOffset] _MainTex("Main Texture", 2D) = "black" {}
}
SubShader{
Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane" }
Fog { Mode Off }
Cull Off
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Lighting Off
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float _WaterSurface;
float _MaskHeight;
float _MaskWidth;
fixed _CutOff;
struct VertexInput {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float4 vertexColor : COLOR;
};
struct VertexOutput {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float4 vertexColor : COLOR;
};
VertexOutput vert(VertexInput v) {
VertexOutput o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
o.vertexColor = v.vertexColor;
return o;
}
float4 frag(VertexOutput i) : COLOR {
float4 texColor = tex2D(_MainTex, i.uv);
const float PI = 3.1415926535897932384626433832795;
fixed height = _MaskHeight * sin(((i.worldPos.x - _MaskWidth * 0.5)/_MaskWidth) * PI);
texColor.a = lerp(0.0, texColor.a,step( _WaterSurface, i.worldPos.y - height ));
return texColor;
}
ENDCG
}
}
}
I would love to hear some suggestions, comments about it to maximize the upsides and minimize the downsides.
** note ** We are targeting mobile devices, that is why I opted out of using Clip since the pixels that are transparent are a very small area and thus do not really impact overdraw.