夜風のMixedReality

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

MixedRealityGraphicsTools StndardShader全機能解説 その③ RenderingModeの実装を見る 初期処理

今回はMRGT調査枠です。

今回は前回に続きGraphicsTools/StandardシェーダーのRenderingModeの実装を見ています。

〇RenderigModeの処理

MRGTShaderではRenderingModeで選択したモードに応じて表示が変わるようになっています。

redhologerbera.hatenablog.com

この処理はBaseShaderGUI.csで行われています。今回はこの処理を追ってどのように表示を切り替えていくのか追っていきます。

BaseShaderGUI.csGraphicsTools/StandardシェーダーのカスタムGUIであるStandardShaderGUIによって継承されているクラスです。

    public class StandardShaderGUI : BaseShaderGUI
    {
    }

ここでは主にレンダリングオプションなどUnityの提供するカスタムシェーダーGUIのクラスをカスタマイズして表示できる機能が定義されています。

 ShaderGUIクラスではOnGUI()関数に沿ってマテリアルのインスペクターを表示させています。

     public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
        {
            Material material = (Material)materialEditor.target;

            FindProperties(props);
            Initialize(material);

            RenderingModeOptions(materialEditor);
        }

materialEditor.targetは表示対象のマテリアルが入ります。

docs.unity3d.com

FindProperties()ではシェーダーのレンダリングモードに関するパラメータを取得しています。

    /// <summary>
        /// Looks for common properties associated with render mode.
        /// </summary>
        /// <param name="props">Material properties to search.</param>
        protected virtual void FindProperties(MaterialProperty[] props)
        {
            renderingMode = FindProperty(BaseStyles.renderingModeName, props);
            customRenderingMode = FindProperty(BaseStyles.customRenderingModeName, props);
            sourceBlend = FindProperty(BaseStyles.sourceBlendName, props);
            destinationBlend = FindProperty(BaseStyles.destinationBlendName, props);
            sourceBlendAlpha = FindProperty(BaseStyles.sourceBlendAlphaName, props);
            destinationBlendAlpha = FindProperty(BaseStyles.destinationBlendAlphaName, props);
            blendOperation = FindProperty(BaseStyles.blendOperationName, props);
            depthTest = FindProperty(BaseStyles.depthTestName, props, false);
            depthWrite = FindProperty(BaseStyles.depthWriteName, props);
            depthOffsetFactor = FindProperty(BaseStyles.depthOffsetFactorName, props);
            depthOffsetUnits = FindProperty(BaseStyles.depthOffsetUnitsName, props);
            colorWriteMask = FindProperty(BaseStyles.colorWriteMaskName, props, false);
            colorWriteMask = colorWriteMask == null ? FindProperty(BaseStyles.colorWriteMaskUIName, props) : colorWriteMask;

            cullMode = FindProperty(BaseStyles.cullModeName, props);
            renderQueueOverride = FindProperty(BaseStyles.renderQueueOverrideName, props);
        }

 ここで見てわかる通りここでShader側のプロパティブロックで定義されているレンダリングオプションのプロパティが取得されていることがわかります。

 

Initialize()ではマテリアルの初期パラメータを設定しています。

        protected void Initialize(Material material)
        {
            if (!initialized)
            {
                MaterialChanged(material);
                initialized = true;
            }
        }

 ここでは初回以降はinitializedがtrueとなるため最初の一回のみ処理が走ります。

 ここでやっているのはSetupMaterialWithRenderingMode()にマテリアル、現在のレンダリングモード、レンダリングモードがCustomの場合使用される二つ目のレンダリングモードおよびレンダーキューが引数として渡されます。

            SetupMaterialWithRenderingMode(material,
                (RenderingMode)renderingMode.floatValue,
                (RenderingMode)customRenderingMode.floatValue,
                (int)renderQueueOverride.floatValue);

このSetupMaterialWithRenderingMode()では初期のレンダリングモードの表示の処理がおこなれています。

  protected static void SetupMaterialWithRenderingMode(・・・)
        {
            //カスタムレンダリングモードを使用しない場合すべてデフォルト値を入れる
            if (mode != RenderingMode.Custom)
            {
              ・・・
            }

            switch (mode)
            {
                case RenderingMode.Opaque:
                    {
                     ・・・
                    }
                    break;

                case RenderingMode.Cutout:
                    {
                       ・・・
                    }
                    break;

                case RenderingMode.Fade:
                    {
         ・・・
                    }
                    break;

                case RenderingMode.Transparent:
                    {
      ・・・
                   }
                    break;

                case RenderingMode.Additive:
                    {
                     ・・・
                    }
                    break;

                case RenderingMode.Custom:
                    {
                        ・・・
                    }
                    break;
            }
        }

カスタムレンダリングモード以外の場合まず次のように値が定義されています。

パラメータ
BlendOp Add
depthTest LessEqual
depthOffsetFactor 0
depthOffsetUnits 0
colorWriteMask All
            if (mode != RenderingMode.Custom)
            {
                material.SetInt(BaseStyles.blendOperationName, (int)BlendOp.Add);
                material.SetInt(BaseStyles.depthTestName, (int)CompareFunction.LessEqual);
                material.SetFloat(BaseStyles.depthOffsetFactorName, 0.0f);
                material.SetFloat(BaseStyles.depthOffsetUnitsName, 0.0f);
                material.SetInt(BaseStyles.colorWriteMaskName, (int)ColorWriteMask.All);
                material.SetInt(BaseStyles.colorWriteMaskUIName, (int)ColorWriteMask.All);
            }

〇レンダリングモードがOpaqueの場合

パラメータ
renderingModeNames Opaque
customRenderingModeName Opaque
sourceBlend One
destinationBlend Zero
depthWrite On
RenderQueue Geometry
    switch (mode)
            {
                case RenderingMode.Opaque:
                    {
                        material.SetOverrideTag(BaseStyles.renderTypeName, BaseStyles.renderingModeNames[(int)RenderingMode.Opaque]);
                        material.SetInt(BaseStyles.customRenderingModeName, (int)RenderingMode.Opaque);
                        material.SetInt(BaseStyles.sourceBlendName, (int)BlendMode.One);
                        material.SetInt(BaseStyles.destinationBlendName, (int)BlendMode.Zero);
                        material.SetInt(BaseStyles.depthWriteName, (int)DepthWrite.On);
                        material.DisableKeyword(BaseStyles.alphaTestOnName);
                        material.DisableKeyword(BaseStyles.alphaBlendFadeOnName);
                        material.DisableKeyword(BaseStyles.alphaBlendTransOnName);
                        material.DisableKeyword(BaseStyles.additiveOnName);
                        material.renderQueue = (renderQueueOverride >= 0) ? renderQueueOverride : (int)RenderQueue.Geometry;
                    }

Opaqueが選択されている場合Blendなどのα値に必要なパラメータは非表示にされています。

〇Cutoutのレンダリングモードを使用している場合

パラメータ
renderingModeNames Cutout
customRenderingModeName Cutout
sourceBlend One
destinationBlend Zero
depthWrite On
RenderQueue Geometry

また_ALPHATEST_ONのシェーダーキーワードをオンにしています。

   case RenderingMode.Cutout:
                    {
                        material.SetOverrideTag(BaseStyles.renderTypeName, BaseStyles.renderingModeNames[(int)RenderingMode.Cutout]);
                        material.SetInt(BaseStyles.customRenderingModeName, (int)RenderingMode.Cutout);
                        material.SetInt(BaseStyles.sourceBlendName, (int)BlendMode.One);
                        material.SetInt(BaseStyles.destinationBlendName, (int)BlendMode.Zero);
                        material.SetInt(BaseStyles.depthWriteName, (int)DepthWrite.On);
                        material.EnableKeyword(BaseStyles.alphaTestOnName);
                        material.DisableKeyword(BaseStyles.alphaBlendFadeOnName);
                        material.DisableKeyword(BaseStyles.alphaBlendTransOnName);
                        material.DisableKeyword(BaseStyles.additiveOnName);
                        material.renderQueue = (renderQueueOverride >= 0) ? renderQueueOverride : (int)RenderQueue.AlphaTest;
                    }
                    break;

Cutoutを使用している場合シェーダーキーワードの中で_ALPHATEST_ONをオンにしています。

〇Fadeのレンダリングモードを使用している場合

パラメータ
renderingModeNames Fade
customRenderingModeName Fade
sourceBlend SrcAlpha
destinationBlend OneMinusSrcAlpha
depthWrite Off
RenderQueue Transparent

また_ALPHABLEND_ONのシェーダーキーワードが有効化されます。

  case RenderingMode.Fade:
                    {
                        material.SetOverrideTag(BaseStyles.renderTypeName, BaseStyles.renderingModeNames[(int)RenderingMode.Fade]);
                        material.SetInt(BaseStyles.customRenderingModeName, (int)RenderingMode.Fade);
                        material.SetInt(BaseStyles.sourceBlendName, (int)BlendMode.SrcAlpha);
                        material.SetInt(BaseStyles.destinationBlendName, (int)BlendMode.OneMinusSrcAlpha);
                        material.SetInt(BaseStyles.depthWriteName, (int)DepthWrite.Off);
                        material.DisableKeyword(BaseStyles.alphaTestOnName);
                        material.EnableKeyword(BaseStyles.alphaBlendFadeOnName);
                        material.DisableKeyword(BaseStyles.alphaBlendTransOnName);
                        material.DisableKeyword(BaseStyles.additiveOnName);
                        material.renderQueue = (renderQueueOverride >= 0) ? renderQueueOverride : (int)RenderQueue.Transparent;
                    }

〇Transparentのレンダリングモードを使用している場合

パラメータ
renderingModeNames Fade
customRenderingModeName Fade
sourceBlend One
destinationBlend OneMinusSrcAlpha
depthWrite Off
RenderQueue Transparent

また_ALPHABLEND_TRANS_ONのシェーダーキーワードが有効化されます。

   case RenderingMode.Transparent:
                    {
                        material.SetOverrideTag(BaseStyles.renderTypeName, BaseStyles.renderingModeNames[(int)RenderingMode.Fade]);
                        material.SetInt(BaseStyles.customRenderingModeName, (int)RenderingMode.Fade);
                        material.SetInt(BaseStyles.sourceBlendName, (int)BlendMode.One);
                        material.SetInt(BaseStyles.destinationBlendName, (int)BlendMode.OneMinusSrcAlpha);
                        material.SetInt(BaseStyles.depthWriteName, (int)DepthWrite.Off);
                        material.DisableKeyword(BaseStyles.alphaTestOnName);
                        material.DisableKeyword(BaseStyles.alphaBlendFadeOnName);
                        material.EnableKeyword(BaseStyles.alphaBlendTransOnName);
                        material.DisableKeyword(BaseStyles.additiveOnName);
                        material.renderQueue = (renderQueueOverride >= 0) ? renderQueueOverride : (int)RenderQueue.Transparent;
                    }

〇Adittiveのレンダリングモードを使用している場合

パラメータ
renderingModeNames Fade
customRenderingModeName Fade
sourceBlend One
destinationBlend One
depthWrite Off
RenderQueue Transparent

また_ADDITIVE_ONのシェーダーキーワードが有効化されます。

  case RenderingMode.Additive:
                    {
                        material.SetOverrideTag(BaseStyles.renderTypeName, BaseStyles.renderingModeNames[(int)RenderingMode.Fade]);
                        material.SetInt(BaseStyles.customRenderingModeName, (int)RenderingMode.Fade);
                        material.SetInt(BaseStyles.sourceBlendName, (int)BlendMode.One);
                        material.SetInt(BaseStyles.destinationBlendName, (int)BlendMode.One);
                        material.SetInt(BaseStyles.depthWriteName, (int)DepthWrite.Off);
                        material.DisableKeyword(BaseStyles.alphaTestOnName);
                        material.DisableKeyword(BaseStyles.alphaBlendFadeOnName);
                        material.DisableKeyword(BaseStyles.alphaBlendTransOnName);
                        material.EnableKeyword(BaseStyles.additiveOnName);
                        material.renderQueue = (renderQueueOverride >= 0) ? renderQueueOverride : (int)RenderQueue.Transparent;
                    }

カスタムの場合は別途定義されています。

このあたりは少し複雑ですがすべてのシェーダーにおいて汎用的に使いまわせる内容ですのでしっかり学んでいきます。