【Unity】【シェーダ】【エディタ拡張】BlendModeをインスペクタから指定する

MaterialのInspectorでブレンドモード(加算とか乗算とか)を選べるようにしてみます。

シェーダ

まずシェーダはこんな感じに作ります。

Shader "Example"
{
    Properties {
        [HideInInspector]_BlendMode("Blend Mode", int)      = 0
        _BlendSrc("Blend Src", int)                         = 1
        _BlendDst("Blend Dst", int)                         = 0
    }
    SubShader
    {

        Tags{ "Queue"="Transparent" "RenderType"="Transparent" }
        
        Pass
        {
            ColorMask RGB
            Blend [_BlendSrc] [_BlendDst]

            CGPROGRAM
            
           #pragma vertex vert
           #pragma fragment frag

           #include "UnityCG.cginc"
            
            
            struct appdata
            {
                float4 vertex       : POSITION;
            };

            struct v2f
            {
                float4 vertex       : SV_POSITION;
            };
            
            v2f vert (appdata v)
            {
                v2f o           = (v2f)0;

                o.vertex        = UnityObjectToClipPos(v.vertex );

                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                return 0.5;
            }

            ENDCG
        }
    }

    CustomEditor "ExampleShaderGUI"
}

_BlendSrc_BlendDstをBlendの指定に使います。
ここにはUnityEngine.Rendering.BlendModeの値を入れます。 この値と_BlendModeの値は次節のスクリプトにより外側から値を入れます。
そのために布石としてExampleShaderGUIをカスタムエディタとして設定しています。

インスペクタ拡張

カスタムエディタのスクリプトは次のように書きます。

using UnityEditor;

public class ExampleShaderGUI : ShaderGUI 
{
    public enum BlendMode
    {
        // ブレンドしない(上書き)
        None                = 0,
        // 加算合成
        Add                 = 1,
        // アルファ値を乗算してから加算合成
        TransparentAdd      = 2,
        // アルファブレンド
        AlphaBlend          = 3,
        // 乗算合成
        Multiply            = 4
    }

    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
    {
        var blendModePropName   = "_BlendMode";
        var blendModeProp       = FindProperty(blendModePropName, properties);
        var blendMode           = (BlendMode)blendModeProp.floatValue;
        using (var scope = new EditorGUI.ChangeCheckScope()) {
            blendMode           = (BlendMode)EditorGUILayout.EnumPopup(ObjectNames.NicifyVariableName(blendModePropName), blendMode);
            if (scope.changed) {
                SetBlend(blendMode, properties);
                blendModeProp.floatValue    = (float)blendMode;
            }
        }
    }

    private void SetBlend(BlendMode blendMode, MaterialProperty[] properties)
    {
        var blendSrc        = FindProperty("_BlendSrc", properties);
        var blendDst        = FindProperty("_BlendDst", properties);
        
        switch (blendMode) {
        case BlendMode.None:
            blendSrc.floatValue     = (float)UnityEngine.Rendering.BlendMode.One;
            blendDst.floatValue     = (float)UnityEngine.Rendering.BlendMode.Zero;
            break;
        case BlendMode.Add:
            blendSrc.floatValue     = (float)UnityEngine.Rendering.BlendMode.One;
            blendDst.floatValue     = (float)UnityEngine.Rendering.BlendMode.One;
            break;
        case BlendMode.TransparentAdd:
            blendSrc.floatValue     = (float)UnityEngine.Rendering.BlendMode.SrcAlpha;
            blendDst.floatValue     = (float)UnityEngine.Rendering.BlendMode.One;
            break;
        case BlendMode.AlphaBlend:
            blendSrc.floatValue     = (float)UnityEngine.Rendering.BlendMode.SrcAlpha;
            blendDst.floatValue     = (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha;
            break;
        case BlendMode.Multiply:
            blendSrc.floatValue     = (float)UnityEngine.Rendering.BlendMode.DstColor;
            blendDst.floatValue     = (float)UnityEngine.Rendering.BlendMode.Zero;
            break;
        default:
            break;
        }
    }
}

入力されたBlendModeにより_BlendSrc_BlendDstの値を書き換えています。

結果

下記のようにインスペクタからブレンドモードを指定できるようになります。

f:id:halya_11:20181112153123p:plain