夜風のMixedReality

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

Shaderの変更を保持して使用できるAssignNewShaderToMaterialを触る その①AssignNewShaderToMateria

本日はShader学習枠です。

 現在MixedRealityToolkitのGraphicsToolsに対して機能開発を行いPRを出しています。

 ここではShaderに新しい関数を実装し、表現の幅を広げる実装を行いましたが、PRで次のような修正依頼のフィードバックをいただきました。

Could you also copy the emission map property from the standard shader in the AssignNewShaderToMaterial function below?

This way users will keep their settings when switching shaders. 😊

github.com

ここでUnityのShaderGUIクラスによって提供されているAssignNewShaderToMaterialという関数を知らなかったので今回PRでいただいた変更を行う前に勉強していきます。

〇AssignNewShaderToMaterial

AssignNewShaderToMaterialはShaderGUIクラスで提供されている関数になります。

この関数はUnityのインスペクタウィンドウからマテリアルに割り当てられているShaderを変更した際に発火する処理で、あるシェーダーで設定したパラメータを差し替えた別のシェーダーで同じパラメータがある場合情報を引き継ぐという役割があります。

 3つの引数を持ちそれぞれ差し替えるShaderのパラメータを保持したMaterial、差し替える前のShaderであるOldShader、差し替える先のShaderdであるNewShaderを持っています

MRGTのStandardShaderGUI.csでは440行目付近に関数があります。

        public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
        {
            ...
        }

ShaderGUI-AssignNewShaderToMaterial - Unity スクリプトリファレンス

〇AssignNewShaderToMateriaの使い方 ①

MRGTStandardShaderではまずもともとのシェーダー変数名と新たな変数名で異なる可能性があるものをキャッシュとして宣言しています。

  public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
        {
            float? smoothness = GetFloatProperty(material, "_Glossiness");
            float? diffuse = GetFloatProperty(material, "_UseDiffuse");
            float? specularHighlights = GetFloatProperty(material, "_SpecularHighlights");
            float? normalMap = null;
            Texture normalMapTexture = material.HasProperty("_BumpMap") ? material.GetTexture("_BumpMap") : null;
            float? emission = null;
            Color? emissionColor = GetColorProperty(material, "_EmissionColor");
            float? reflections = null;
            float? rimLighting = null;
            Vector4? textureScaleOffset = null;
            float? cullMode = GetFloatProperty(material, "_Cull");
            bool newShaderIsStandardCanvas = newShader.name == StandardShaderUtility.GraphicsToolsStandardCanvasShaderName;

         ...

ここでは以下のプロパティに関してキャッシュ保持が働いています。

 ・Smoothness

 ・BumpMap

 ・emissionColor

 ・rimLighting

・cullMode

これはoldShaderのプロパティ(MRGTStandardに変更する前のShaderの持つプロパティ)でありこれは次の行処理で宣言されています。

  if (oldShader)
            {
                if (oldShader.name.Contains("Standard"))
                {
                    normalMap = material.IsKeywordEnabled("_NORMALMAP") ? 1.0f : 0.0f;
                    emission = material.IsKeywordEnabled("_EMISSION") ? 1.0f : 0.0f;
                    reflections = GetFloatProperty(material, "_GlossyReflections");
                }
                else if (oldShader.name.Contains("Fast Configurable"))
                {
                    normalMap = material.IsKeywordEnabled("_USEBUMPMAP_ON") ? 1.0f : 0.0f;
                    emission = GetFloatProperty(material, "_UseEmissionColor");
                    reflections = GetFloatProperty(material, "_UseReflections");
                    rimLighting = GetFloatProperty(material, "_UseRimLighting");
                    textureScaleOffset = GetVectorProperty(material, "_TextureScaleOffset");
                }
            }

ここではOldShaderの名前がStandardである場合及びDast Configurableの場合とそれ以外で分岐しています。

 StandardのシェーダーからMRGTStandardShaderへ変更する場合ノーマルマップが使用されているか? 発光は使用されているか? リフレクションは使用されているか?の3つの情報を取得しています。

 今回は長くなってしまったので続きは明日の記事でまとめていきます。