[Unity] Spine 오브젝트를 Mask하기
Spine 오브젝트는?
Spine 개체는 Unity에서 말하는 MeshRenderer로 렌더링되고 있습니다.
(spine-unity의 SkeletonRenderer.cs가 해당 소스입니다)
즉, MeshRenderer의 Mask 처리를 만들 수 있다면, Mask를 사용할 수 있게 됩니다.
(왜 이런 엄한 부분을 가지고 예제를 만든 걸까...)
Mask 처리에 대해
요는 Renderer를 Mask하면 되는 것이지만,
SpriteRenderer 자체를 Mask하는 처리는 Unity에는 없는 것 같습니다.
그래서, 간단히 자작하기로 했습니다.
Shader로 실제 제작
간단한 것은 역시 스텐실 테스트를 사용하는 것이군요.
아주 간단하게 설명하면, 스텐실이란 모양을 도려낸다는 의미로
픽셀 렌더링을 할 때 이 점을 찍는가 찍지 않는다인지를 판정하는 테스트입니다.
이것을 이용합니다.
Spine 쪽에 적용하는 shader
SpineShader.shaderShader "Custom/SpineShader"{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader
{
Tags {"Queue"="Transparent+2" "IgnoreProjector"="True" "RenderType"="Transparent"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Stencil {
Ref 1
Comp Equal
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata_t
{
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
half2 texcoord : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata_t v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
fixed4 frag (v2f i) : COLOR
{
fixed4 col = tex2D(_MainTex, i.texcoord);
return col;
}
ENDCG
}
}
}
Mask할 Sprite에 설정하는 Shader
SpineSoriteMask.shaderShader "Custom/SpineSpriteMask"{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader
{
Tags {"Queue"="Transparent+1" "IgnoreProjector"="True"}
ZWrite Off
AlphaTest Greater 0.5
ColorMask 0
ZTest Always
Stencil {
Ref 1
Comp always
Pass replace
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata_t
{
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
half2 texcoord : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata_t v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
fixed4 frag (v2f i) : COLOR
{
fixed4 col = tex2D(_MainTex, i.texcoord);
if(col.a<0.1)discard;
return col;
}
ENDCG
}
}
}
해설
SpineShader.shader Stencil {
Ref 1
Comp Equal
}
SpineSoriteMask.shader ColorMask 0
Stencil {
Ref 1
Comp always
Pass replace
}
Stencil
해설에 대해서는
edo_m18 씨의 [Unity] Unity의 Shader 스텐실 버퍼를 시도
를 참고하십시오.
먼저, SpineSpriteMask 입니다만,
"참조 값 1의 것과 비교하고, 모두 OK로 해서,
참조 값을 버퍼에 기록하고, ColorMask 0 으로 묘화는 하지 않음"
이 됩니다.
그리고 SpineShader.
"참조 값은 1, 값의 일치를 체크"
가 됩니다.
이 설정을 함으로써
SpineShader 측의 묘화는 StencilTest 를 받게 되고,
SpineSpriteMask 측에서 설정한 모양대로 도려내지도록 그려집니다.
Unity에서 사용할 때에는 Material화 시킬 필요가 있습니다만,
그에 대해서는
github
여기를 참고하십시오.
---
* 스파인측 설정
* 마스크이미지측 설정
* 매터리얼 설정은 이렇게(특별히 이미지는 지정하지 않고 쉐이더만 넣음)