今回はMRGT調査枠です。
今回は前回に続きGraphicsTools/StandardシェーダーのRenderingModeの実装を見ています。
〇RenderigModeの処理
MRGTShaderではRenderingModeで選択したモードに応じて表示が変わるようになっています。

この処理はBaseShaderGUI.csで行われています。今回はこの処理を追ってどのように表示を切り替えていくのか追っていきます。
BaseShaderGUI.csはGraphicsTools/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は表示対象のマテリアルが入ります。
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;
}
カスタムの場合は別途定義されています。
このあたりは少し複雑ですがすべてのシェーダーにおいて汎用的に使いまわせる内容ですのでしっかり学んでいきます。