夜風のMixedReality

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

ゼロから始めるUnityShader開発 CustomShaderGUIでマテリアルのプロパティをカスタマイズする ShaderGUIの使い方とTextureのカスタマイズ

本日はShader勉強枠です。

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

〇CustomShaderGUIとは?

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

CustomShaderGUIの例(MRGT Shader)

 この機能を使用することで例えばEnum型でプロパティを設定することや、レイアウトを変えること、ある機能を有効にしている場合のみその機能に関連するプロパティを表示させるということができます。

〇CustomShaderGUIを使用する

CustomShaderGUIを使用するためには次のようにシェーダー側に定義します。

Shader "Unlit/ShaderGUITest"
{
    Properties
    {
       ・・・
    }
    SubShader
    {
  ・・・
        Pass
        {
            CGPROGRAM
   ・・・
            ENDCG
        }
    }
      CustomEditor "(C#クラス名)"//追加
}

次にどのようにカスタマイズするのかを指定するC#のクラスを作成します。

このクラスはShaderGUIを継承する必要があり、最小の構成は次のようになります。

using UnityEditor;
using UnityEngine;

public class CustomShaderGUITest : ShaderGUI
{
    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
    {
        
    }
}

OnGUI()がマテリアルの表示に使用される関数です。

今回はCustomShaderGUITestというクラスを作成しましたのでShader側のEditorGUIは次のようになります。

Shader "Unlit/ShaderGUITest"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
  ・・・
        Pass
        {
            CGPROGRAM
   ・・・
            ENDCG
        }
    }
      CustomEditor "CustomShaderGUITest"
}

この状態でマテリアルの表記は次のようになります。

 この時点ではOnGUI()の中身に何も定義していないため何も表示されませんが、本来であれば表示されるはずの_MainTexのプロパティ表示も行われないことが確認できます。

 これはCustomShaderGUIによる表示によってもともとのプロパティ表示が上書きされていることを意味しており、CustomShaderGUIが機能していることを意味しています。

〇ラベルの作成

OnGUIの中身に次のような処理を実装します。

    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
    {
        EditorGUILayout.LabelField("MainFeature");
    }

〇Shaderのプロパティの取得

Shaderのプロパティを取得するためにはFindProperty(プロパティ名,MaterialProperty[])を使用します。

    protected MaterialProperty albedoMap;
    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
    {
        EditorGUILayout.LabelField("MainFeature");
        albedoMap = FindProperty("_MainTex", props);
    }

これによってShader側の_MainTexを取得できました。

〇プロパティの表示

取得したプロパティを表示させます。

    protected MaterialProperty albedoMap;
    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
    {
        EditorGUILayout.LabelField("MainFeature");
        albedoMap = FindProperty("_MainTex", props);
        
        materialEditor.ShaderProperty(albedoMap,"MainTexture");//追加
    }

これによってShaderGUIを使用しない場合と同様にプロパティが表示されます。

〇テクスチャ用のカスタムレイアウトを使用する

CustomGUIではいくつかの専用のレイアウトが提供されています。

その代表例としてテクスチャの表示をプロパティ名と合わせるということができます。

using UnityEditor;
using UnityEngine;

public class CustomShaderGUITest : ShaderGUI
{
    protected static class Styles
    {
        public static readonly GUIContent albedoMap = new GUIContent("MainTexture", "MainMap");
    }

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

materialEditor.TexturePropertySingleLineを使用することで上記のレイアウトは実現できます。

 第一引数にはレイアウト、第二引数にShaderのプロパティで実装します。

 ここではStylesというクラスを作成し、読み取り専用でGUIContentとしてプロパティを作成しました。

 GUIContentは第一引数にマテリアルの表示名、第二引数にマテリアルのプロパティ上でカーソルを合わせ続けた場合に表示されるヒントのテキストを指定します。

 これによって_MainTexの表示をカスタムすることができました。

〇参考

docs.unity3d.com