30
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

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

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
こちらを参考にしてください。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
30
Help us understand the problem. What are the problem?