夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

ゼロから始めるUnityShader開発 CustomShaderGUIでマテリアルをカスタマイズする Enum型のプロパティを表示する

本日はShader学習枠です。

今回はShader自体というよりはShaderをUnity上に表示させる際に使用できるカスタマイズ表示を実装します。

〇CustomShaderGUIとは?

CustomShaderGUIはUnityのShaderLabで使用することができる機能で、C#を用いてインスペクターウィンドウに表示されるマテリアルプロパティをカスタマイズできます。

CustomShaderGUIの例(MRGT Shader)

これまではShaderGUIの基本的な実装とテクスチャのレイアウト、プロパティの状況に応じて表示のオンオフの切り替えなどを実装してきました。

redhologerbera.hatenablog.com

redhologerbera.hatenablog.com

今回はCustomShaderGUIでEnum型を実装します。

テクスチャやチェックボックスはCustomShaderGUIを使用しなくてもShaderLabの機能として行うこと自体はできますが、Enum型はCustomShaderGUIを使用しないと実装できない手法になります。

〇Enum型のマテリアルプロパティの実装

Enum型を使用するためにはCustomShaderGUI側で定義を行う必要があります。

public class CustomShaderGUITest : ShaderGUI
{
    public enum Mode
    {
        ModeA = 0,
        ModeB = 1,
        ModeC = 2
    }

今回はテスト用にModeとしてABCの3つを定義しました。

次にシェーダーがわでプロパティに_Modeという変数を追加します。

この際にアトリビュートとして[Enum(カスタムシェーダーGUIのEnum)]を指定します。

    Properties
    {
          [Enum(CustomShaderGUITest.Mode)] _Mode("Mode", Float) = 0 
    }

次にカスタムシェーダーGUIのレイアウトを定義するクラスになるStylesに2つの変数を定義します。

    protected static class Styles
    {
   ・・・
        public static readonly GUIContent Mode = new GUIContent("Mode", ".");
        public static readonly string[] ModeNames = new string[] { "ModeA", "ModeB", "ModeC" };
    }

GUIContent Modeは表示用のUIになります。

string[] ModeNamesはEnum型として使用する際の子プロパティ(Enumで指定できる値)をString型で記述します。

最後に実際の表示を行う関数であるOnGUI(){}に表示処理を定義します。

   EditorGUILayout.Popup(Styles.Mode,mode.intValue, Styles.ModeNames);
       

EditorGUILayout.PopupはUnityで提供されているEnumなどのポップアップを定義することができます。第一引数にどのように記述するか(StylesのMode)、第二引数にシェーダーのどの変数を紐づけるか? 第三引数にポップアップの子変数を定義します。

これによってマテリアルのプロパティとしてEnum型が使用可能になります。

本日は以上です。

〇カスタムシェーダーGUIの全コード

using UnityEditor;
using UnityEngine;

public class CustomShaderGUITest : ShaderGUI
{
    
    
    public enum Mode
    {
        ModeA = 0,
        ModeB = 1,
        ModeC = 2
    }
    
    protected static class Styles
    {
        public static readonly GUIContent albedoMap = new GUIContent("MainTexture", "MainMap");
        public static readonly GUIContent Mode = new GUIContent("Mode", ".");
        public static readonly string[] ModeNames = new string[] { "ModeA", "ModeB", "ModeC" };
    }

    
    protected MaterialProperty albedoMap;
    protected MaterialProperty mode;
    
    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
    {
        //  Material material = (Material)materialEditor.target;
        EditorGUILayout.LabelField("MainFeature");
        mode = FindProperty("_Mode", props);
        albedoMap = FindProperty("_MainTex", props);

        EditorGUILayout.Popup(Styles.Mode,mode.intValue, Styles.ModeNames);
        materialEditor.TexturePropertySingleLine(Styles.albedoMap,albedoMap);
       
    }
}