32
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Unity】SpineオブジェクトをMaskする

Posted at

Spineオブジェクトは?

SpineオブジェクトはUnityで言うところのMeshRendererで描画されています。
(spine-unity内のSkeletonRenderer.csが該当のソースです)
つまりMeshRendererのMask処理を書くことが出来れば、Maskすることが出来ます。

名称未設定.mov.gif
(自分はなんでこの身体の位置にしちゃったんだろう?)

Mask処理について

要はRendererをMaskすれば良いのですが、
SpriteRendererすらMaskする処理はUnityには無いようです。
なので、簡単に自作する事にしました。

Shaderで実装

簡単なのはやはりステンシルテストを使うことですね。
すごく簡単に説明しますと、ステンシルとは型抜きという意味で
ピクセル描画を行う際にこの点を打つか打たないかを判定するテストになります。
これを利用します。

Spine側に適用するshader

SpineShader.shader
Shader "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.shader
Shader "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]
(https://github.com/jake1256/SpineMask)
こちらを参考にしてください。

32
30
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?