本日はUnityの小ネタ枠です。
Unityでスクリプトからシェーダのキーワード定義を変更して処理を切り替える方法です。
今回はシェーダの処理をマテリアルごとに切り替えるか、シェーダ全体を切り替える方法を試します。
シェーダバリアント
シェーダーバリアントはシェーダーコードに条件付き動作を導入する方法の 1 つです。
シェーダー内にキーワードを定義するとキーワード毎に分岐した処理を記述でき、内部的には分岐毎に異なるシェーダファイル(バリアント)が作られます。
docs.unity3d.com
スクリプトからシェーダのキーワードを切り替えるにはShader.EnableKeywordまたはShader.DisableKeywordを利用します。
docs.unity3d.com
docs.unity3d.com
// シェーダのキーワードの定義を追加する Shader.EnableKeyword("SHADER_KEYWORD"); // シェーダのキーワードの定義を削除する Shader.DisableKeyword("SHADER_KEYWORD");
マテリアルごとに切り替えたい場合はMaterial.EnableKeywordまたはMaterial.DisableKeywordを利用します。
docs.unity3d.com
docs.unity3d.com
// 対象のマテリアルの参照を取得する Material targetMaterial = _renderer.material; // シェーダのキーワードの定義を追加する targetMaterial.EnableKeyword("SHADER_KEYWORD"); // シェーダのキーワードの定義を削除する targetMaterial.DisableKeyword("SHADER_KEYWORD");
前回記事
以下の記事で作成したサンプルシェーダを基にサンプルを作成します。
bluebirdofoz.hatenablog.com
サンプルスクリプト
スクリプトから特定のマテリアルのキーワードまたはシェーダ全体のキーワードを切り替える以下のサンプルスクリプトを作成しました。
・ShaderKeywordController.cs
using UnityEngine; public class ShaderKeywordController : MonoBehaviour { private readonly string _shaderKeywordRed = "FORCE_RED_COLOR"; private readonly string _shaderKeywordGreen = "FORCE_GREEN_COLOR"; private readonly string _shaderKeywordBlue = "FORCE_BLUE_COLOR"; [SerializeField] Renderer _renderer; /// <summary> /// 全てのキーワードを無効化する /// </summary> [ContextMenu("ResetShaderKeyword")] public void ResetShaderKeyword() { // シェーダのキーワードの定義を削除する Shader.DisableKeyword(_shaderKeywordRed); Shader.DisableKeyword(_shaderKeywordGreen); Shader.DisableKeyword(_shaderKeywordBlue); } /// <summary> /// シェーダー全体に赤色にするキーワードを有効化する /// </summary> [ContextMenu("SetShaderKeywordRed")] public void SetShaderKeywordRed() { // シェーダのキーワードの定義を追加する Shader.EnableKeyword(_shaderKeywordRed); // シェーダのキーワードの定義を削除する Shader.DisableKeyword(_shaderKeywordGreen); Shader.DisableKeyword(_shaderKeywordBlue); } /// <summary> /// 指定のレンダラーが保持するマテリアルのシェーダにのみ赤色にするキーワードを有効化する /// </summary> [ContextMenu("SetMaterialShaderKeywordRed")] public void SetMaterialShaderKeywordRed() { // マテリアルのシェーダのキーワードの定義を追加する _renderer.material.EnableKeyword(_shaderKeywordRed); // シェーダのキーワードの定義を削除する _renderer.material.DisableKeyword(_shaderKeywordGreen); _renderer.material.DisableKeyword(_shaderKeywordBlue); } #if UNITY_EDITOR private void OnApplicationQuit() { ResetShaderKeyword(); } #endif }
スクリプトをシーンに設定して変更対象のマテリアルの参照を追加します。
動作確認
シーンを再生して動作を確認します。
コンテキストメニューからスクリプトの処理を実行してキーワードを切り替えます。
マテリアル指定の関数を実行すると、指定のマテリアルのシェーダのみ処理が切り替わり発色が変わりました。
シェーダ指定の関数を実行すると、シェーダ全体にキーワードが設定されるため、全ての処理が切り替わり発色が変わりました。