Open7

UnityのURP-MToon触ってみたメモ

toshidesutoshidesu

背景

目的

  • バーチャルライブでどんな感じで使えるかをチェックしたい
  • VRMへのライトの当たり方をチェックできるプロジェクトあれば便利そう
  • アバターをサクサク差し替えたい

スコープ

  • ランタイムでURPプロジェクトにVRMを入れる

制約

  • unitypackageとして出せる状態にする

前提

  • 特になし
toshidesutoshidesu

VRMモデル導入

問題

  • .vrmが.fbxに展開されない

検討

解決

toshidesutoshidesu

URP-MToon利用

  • mtoon_urpのパスは以下参照
  • デフォルトでピンク表示で、結局手作業でシェーダ切り替えすることになる

問題

  • シェーダ一括変換スクリプトで動的に切り替えたいが、不具合がある
  • 半透明系のシェーダが入ってると使えないのかな?
  • もし動的変更でうまくいかないなら、URP対応のMToonはあまり意味がない
  • もしかしたらVroid_SampleB特有のバグかも

解決

  • AlphaModeをcutoutに変更すれば直るが、ランタイムでcutoutのパラメータを引き継いでも、再度別のパラメータに変えてまたcutoutにしないと変更が反映されない
  • いずれにせよランタイムで変更しても不具合が出ることに変わりない
  • 不具合があったモデルは使わないという方針で、いったん運用でなんとかする
toshidesutoshidesu

ランタイムロード機能を入れる

  • ランタイムロードをする際に、vrm0系の知見を使えないなら、わざわざ1系にしてまでMToonのURPを使おうとは思わない
toshidesutoshidesu

シェーダ変換スクリプト

使い方

ステップ1: スクリプトの配置

  • シーン内の任意の空のオブジェクトを作成し、このスクリプトをそのオブジェクトにアタッチします。

ステップ2: 対象オブジェクトの指定

  • インスペクター上でtargetObjectsフィールドにシェーダーを適用したいオブジェクトをドラッグ&ドロップします。
  • 複数のオブジェクトにシェーダーを適用する場合、配列にそれらのオブジェクトを追加します。

ステップ3: URPシェーダーの指定

  • urpShaderフィールドに切り替えたいURPシェーダーを指定します。必要なURPシェーダーをプロジェクト内で見つけ、そのシェーダーをこのフィールドにドラッグ&ドロップします。

ステップ4: ゲームの開始

  • シーンを再生すると、指定されたオブジェクトのシェーダーが自動的にURPへ切り替わります。

注意事項

  • 正しく動作させるためには、指定するシェーダーがURPに対応している必要があります。
  • オブジェクトがnullまたはシェーダーが未指定の場合、エラーメッセージが表示されます。

このスクリプトを使用することで、ゲーム開始時に自動的に指定したオブジェクトのシェーダーがURPへ切り替わります。

コード

using UnityEngine;

public class MToon2URPSwitcher : MonoBehaviour
{
    public GameObject[] targetObjects;  // 対象となるオブジェクトの配列
    public Shader urpShader;  // URPへ切り替えるためのシェーダー

    private void Start()
    {
        // 開始時に全ターゲットにシェーダーを適用
        foreach (var target in targetObjects)
        {
            ApplyShader(target);
        }
    }

    private void ApplyShader(GameObject target)
    {
        // シェーダーが指定されていない場合のエラー処理
        if (urpShader == null)
        {
            Debug.LogError("URP shader is not specified.");
            return;
        }

        // ターゲットオブジェクトが指定されていない場合のエラー処理
        if (target == null)
        {
            Debug.LogError("Target object is not specified.");
            return;
        }

        Renderer[] childRenderers = target.GetComponentsInChildren<Renderer>();

        // 各レンダラーに対してマテリアルを変更
        foreach (Renderer renderer in childRenderers)
        {
            Material[] materials = renderer.materials;

            for (int i = 0; i < materials.Length; i++)
            {
                Material originalMaterial = materials[i];
                Material newMaterial = new Material(urpShader);

                // レンダリングとライティングのプロパティをコピー
                CopyRenderingProperties(originalMaterial, newMaterial);
                CopyLightingProperties(originalMaterial, newMaterial);

                materials[i] = newMaterial;
            }

            renderer.materials = materials;
        }
    }

    // レンダリングプロパティのコピー
    private void CopyRenderingProperties(Material original, Material destination)
    {
        CopyProperties(original, destination, "_AlphaMode", "_TransparentWithZWrite", "_Cutoff", "_RenderQueueOffset", "_DoubleSided");
    }

    // ライティングプロパティのコピー
    private void CopyLightingProperties(Material original, Material destination)
    {
        CopyProperties(original, destination, "_Color", "_MainTex", "_ShadeColor", "_ShadeTex", "_BumpMap", "_BumpScale");
    }

    // 指定されたプロパティ名でマテリアルのプロパティをコピー
    private void CopyProperties(Material original, Material destination, params string[] propertyNames)
    {
        foreach (var propName in propertyNames)
        {
            if (original.HasProperty(propName) && destination.HasProperty(propName))
            {
                if (propName == "_MainTex" || propName == "_ShadeTex" || propName == "_BumpMap")
                {
                    destination.SetTexture(propName, original.GetTexture(propName));
                }
                else if (propName == "_Color" || propName == "_ShadeColor")
                {
                    destination.SetColor(propName, original.GetColor(propName));
                }
                else
                {
                    destination.SetFloat(propName, original.GetFloat(propName));
                }
            }
        }
    }
}
toshidesutoshidesu

Appendix

変換前:普通のMToon

VRM10/Universal Render Pipeline/MToon10
Shader "VRM10/Universal Render Pipeline/MToon10"
{
    Properties
    {
        // Rendering
        _AlphaMode ("alphaMode", Int) = 0
        _TransparentWithZWrite ("mtoon.transparentWithZWrite", Int) = 0
        _Cutoff ("alphaCutoff", Range(0, 1)) = 0.5 // Unity specified name
        _RenderQueueOffset ("mtoon.renderQueueOffsetNumber", Int) = 0
        _DoubleSided ("doubleSided", Int) = 0

        // Lighting
        _Color ("pbrMetallicRoughness.baseColorFactor", Color) = (1, 1, 1, 1) // Unity specified name
        _MainTex ("pbrMetallicRoughness.baseColorTexture", 2D) = "white" {} // Unity specified name
        _ShadeColor ("mtoon.shadeColorFactor", Color) = (1, 1, 1, 1)
        _ShadeTex ("mtoon.shadeMultiplyTexture", 2D) = "white" {}
        [Normal] _BumpMap ("normalTexture", 2D) = "bump" {} // Unity specified name
        _BumpScale ("normalTexture.scale", Float) = 1.0 // Unity specified name
        _ShadingShiftFactor ("mtoon.shadingShiftFactor", Range(-1, 1)) = -0.05
        _ShadingShiftTex ("mtoon.shadingShiftTexture", 2D) = "black" {} // channel R
        _ShadingShiftTexScale ("mtoon.shadingShiftTexture.scale", Float) = 1
        _ShadingToonyFactor ("mtoon.shadingToonyFactor", Range(0, 1)) = 0.95

        // GI
        _GiEqualization ("mtoon.giEqualizationFactor", Range(0, 1)) = 0.9

        // Emission
        [HDR] _EmissionColor ("emissiveFactor", Color) = (0, 0, 0, 1) // Unity specified name
        _EmissionMap ("emissiveTexture", 2D) = "white" {} // Unity specified name

        // Rim Lighting
        _MatcapColor ("mtoon.matcapFactor", Color) = (0, 0, 0, 1)
        _MatcapTex ("mtoon.matcapTexture", 2D) = "black" {}
        _RimColor ("mtoon.parametricRimColorFactor", Color) = (0, 0, 0, 1)
        _RimFresnelPower ("mtoon.parametricRimFresnelPowerFactor", Range(0, 100)) = 5.0
        _RimLift ("mtoon.parametricRimLiftFactor", Range(0, 1)) = 0
        _RimTex ("mtoon.rimMultiplyTexture", 2D) = "white" {}
        _RimLightingMix ("mtoon.rimLightingMixFactor", Range(0, 1)) = 1

        // Outline
        _OutlineWidthMode ("mtoon.outlineWidthMode", Int) = 0
        [PowerSlider(2.2)] _OutlineWidth ("mtoon.outlineWidthFactor", Range(0, 0.05)) = 0
        _OutlineWidthTex ("mtoon.outlineWidthMultiplyTexture", 2D) = "white" {} // channel G
        _OutlineColor ("mtoon.outlineColorFactor", Color) = (0, 0, 0, 1)
        _OutlineLightingMix ("mtoon.outlineLightingMixFactor", Range(0, 1)) = 1

        // UV Animation
        _UvAnimMaskTex ("mtoon.uvAnimationMaskTexture", 2D) = "white" {} // channel B
        _UvAnimScrollXSpeed ("mtoon.uvAnimationScrollXSpeedFactor", Float) = 0
        _UvAnimScrollYSpeed ("mtoon.uvAnimationScrollYSpeedFactor", Float) = 0
        _UvAnimRotationSpeed ("mtoon.uvAnimationRotationSpeedFactor", Float) = 0

        // Unity ShaderPass Mode
        _M_CullMode ("_CullMode", Float) = 2.0
        _M_SrcBlend ("_SrcBlend", Float) = 1.0
        _M_DstBlend ("_DstBlend", Float) = 0.0
        _M_ZWrite ("_ZWrite", Float) = 1.0
        _M_AlphaToMask ("_AlphaToMask", Float) = 0.0

        // etc
        _M_DebugMode ("_DebugMode", Float) = 0.0

        // for Editor
        _M_EditMode ("_EditMode", Float) = 0.0
    }

    // Shader Model 3.0
    SubShader
    {
        Tags
        {
            "RenderType" = "Opaque"
            "RenderPipeline" = "UniversalPipeline"
            "UniversalMaterialType" = "Lit"
            "IgnoreProjector" = "True"
        }

        // Built-in Forward Base Pass
        Pass
        {
            Name "UniversalForward"
            Tags { "LightMode" = "UniversalForward" }

            Cull [_M_CullMode]
            Blend [_M_SrcBlend] [_M_DstBlend]
            ZWrite [_M_ZWrite]
            ZTest LEqual
            BlendOp Add, Max
            AlphaToMask [_M_AlphaToMask]

            HLSLPROGRAM
            #pragma target 3.0

            // Unity defined keywords
            #pragma multi_compile_fwdbase nolightmap nodynlightmap nodirlightmap novertexlight
            #pragma multi_compile_fog
            #pragma multi_compile_instancing

            #pragma multi_compile __ _ALPHATEST_ON _ALPHABLEND_ON
            #pragma multi_compile __ _NORMALMAP
            #pragma multi_compile __ _MTOON_EMISSIVEMAP
            #pragma multi_compile __ _MTOON_RIMMAP
            #pragma multi_compile __ _MTOON_PARAMETERMAP

            // -------------------------------------
            // Universal Pipeline keywords
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
            #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
            #pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS
            #pragma multi_compile_fragment _ _SHADOWS_SOFT
            #pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
            #pragma multi_compile _ SHADOWS_SHADOWMASK
            #pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION
            
            #pragma vertex MToonVertex
            #pragma fragment MToonFragment

            #define MTOON_URP

            #include "./vrmc_materials_mtoon_forward_vertex.hlsl"
            #include "./vrmc_materials_mtoon_forward_fragment.hlsl"
            ENDHLSL
        }

        // Built-in Forward Base Pass
        Pass
        {
            Name "MToonOutline"
            Tags { "LightMode" = "MToonOutline" }

            Cull Front
            Blend [_M_SrcBlend] [_M_DstBlend]
            ZWrite [_M_ZWrite]
            ZTest LEqual
            Offset 1, 1
            BlendOp Add, Max
            AlphaToMask [_M_AlphaToMask]

            HLSLPROGRAM
            #pragma target 3.0

            // Unity defined keywords
            #pragma multi_compile_fwdbase nolightmap nodynlightmap nodirlightmap novertexlight
            #pragma multi_compile_fog
            #pragma multi_compile_instancing

            #pragma multi_compile __ _ALPHATEST_ON _ALPHABLEND_ON
            #pragma multi_compile __ _NORMALMAP
            #pragma multi_compile __ _MTOON_EMISSIVEMAP
            #pragma multi_compile __ _MTOON_RIMMAP
            #pragma multi_compile __ _MTOON_PARAMETERMAP
            #pragma multi_compile __ _MTOON_OUTLINE_WORLD _MTOON_OUTLINE_SCREEN

            #pragma vertex MToonVertex
            #pragma fragment MToonFragment

            #define MTOON_URP
            #define MTOON_PASS_OUTLINE

            #include "./vrmc_materials_mtoon_forward_vertex.hlsl"
            #include "./vrmc_materials_mtoon_forward_fragment.hlsl"
            ENDHLSL
        }

        //  Shadow rendering pass
        Pass
        {
            Name "ShadowCaster"
            Tags { "LightMode" = "ShadowCaster" }

            Cull [_M_CullMode]
            ZWrite On
            ZTest LEqual

            HLSLPROGRAM
            #pragma target 3.0

            // Unity defined keywords
            #pragma multi_compile_shadowcaster nolightmap nodynlightmap nodirlightmap novertexlight
            #pragma multi_compile_instancing

            #pragma multi_compile __ _ALPHATEST_ON _ALPHABLEND_ON

            #pragma vertex MToonShadowCasterVertex
            #pragma fragment MToonShadowCasterFragment

            #define MTOON_URP
            
            #include "./vrmc_materials_mtoon_shadowcaster_vertex.hlsl"
            #include "./vrmc_materials_mtoon_shadowcaster_fragment.hlsl"
            ENDHLSL
        }
    }

    FallBack "Hidden/Universal Render Pipeline/FallbackError"
    CustomEditor "VRMShaders.VRM10.MToon10.Editor.MToonInspector"
}

変換後:URP対応MToon

VRM10/Universal Render Pipeline/MToon10
Shader "VRM10/Universal Render Pipeline/MToon10"
{
    Properties
    {
        // Rendering
        _AlphaMode ("alphaMode", Int) = 0
        _TransparentWithZWrite ("mtoon.transparentWithZWrite", Int) = 0
        _Cutoff ("alphaCutoff", Range(0, 1)) = 0.5 // Unity specified name
        _RenderQueueOffset ("mtoon.renderQueueOffsetNumber", Int) = 0
        _DoubleSided ("doubleSided", Int) = 0

        // Lighting
        _Color ("pbrMetallicRoughness.baseColorFactor", Color) = (1, 1, 1, 1) // Unity specified name
        _MainTex ("pbrMetallicRoughness.baseColorTexture", 2D) = "white" {} // Unity specified name
        _ShadeColor ("mtoon.shadeColorFactor", Color) = (1, 1, 1, 1)
        _ShadeTex ("mtoon.shadeMultiplyTexture", 2D) = "white" {}
        [Normal] _BumpMap ("normalTexture", 2D) = "bump" {} // Unity specified name
        _BumpScale ("normalTexture.scale", Float) = 1.0 // Unity specified name
        _ShadingShiftFactor ("mtoon.shadingShiftFactor", Range(-1, 1)) = -0.05
        _ShadingShiftTex ("mtoon.shadingShiftTexture", 2D) = "black" {} // channel R
        _ShadingShiftTexScale ("mtoon.shadingShiftTexture.scale", Float) = 1
        _ShadingToonyFactor ("mtoon.shadingToonyFactor", Range(0, 1)) = 0.95

        // GI
        _GiEqualization ("mtoon.giEqualizationFactor", Range(0, 1)) = 0.9

        // Emission
        [HDR] _EmissionColor ("emissiveFactor", Color) = (0, 0, 0, 1) // Unity specified name
        _EmissionMap ("emissiveTexture", 2D) = "white" {} // Unity specified name

        // Rim Lighting
        _MatcapColor ("mtoon.matcapFactor", Color) = (0, 0, 0, 1)
        _MatcapTex ("mtoon.matcapTexture", 2D) = "black" {}
        _RimColor ("mtoon.parametricRimColorFactor", Color) = (0, 0, 0, 1)
        _RimFresnelPower ("mtoon.parametricRimFresnelPowerFactor", Range(0, 100)) = 5.0
        _RimLift ("mtoon.parametricRimLiftFactor", Range(0, 1)) = 0
        _RimTex ("mtoon.rimMultiplyTexture", 2D) = "white" {}
        _RimLightingMix ("mtoon.rimLightingMixFactor", Range(0, 1)) = 1

        // Outline
        _OutlineWidthMode ("mtoon.outlineWidthMode", Int) = 0
        [PowerSlider(2.2)] _OutlineWidth ("mtoon.outlineWidthFactor", Range(0, 0.05)) = 0
        _OutlineWidthTex ("mtoon.outlineWidthMultiplyTexture", 2D) = "white" {} // channel G
        _OutlineColor ("mtoon.outlineColorFactor", Color) = (0, 0, 0, 1)
        _OutlineLightingMix ("mtoon.outlineLightingMixFactor", Range(0, 1)) = 1

        // UV Animation
        _UvAnimMaskTex ("mtoon.uvAnimationMaskTexture", 2D) = "white" {} // channel B
        _UvAnimScrollXSpeed ("mtoon.uvAnimationScrollXSpeedFactor", Float) = 0
        _UvAnimScrollYSpeed ("mtoon.uvAnimationScrollYSpeedFactor", Float) = 0
        _UvAnimRotationSpeed ("mtoon.uvAnimationRotationSpeedFactor", Float) = 0

        // Unity ShaderPass Mode
        _M_CullMode ("_CullMode", Float) = 2.0
        _M_SrcBlend ("_SrcBlend", Float) = 1.0
        _M_DstBlend ("_DstBlend", Float) = 0.0
        _M_ZWrite ("_ZWrite", Float) = 1.0
        _M_AlphaToMask ("_AlphaToMask", Float) = 0.0

        // etc
        _M_DebugMode ("_DebugMode", Float) = 0.0

        // for Editor
        _M_EditMode ("_EditMode", Float) = 0.0
    }

    // Shader Model 3.0
    SubShader
    {
        Tags
        {
            "RenderType" = "Opaque"
            "RenderPipeline" = "UniversalPipeline"
            "UniversalMaterialType" = "Lit"
            "IgnoreProjector" = "True"
        }

        // Built-in Forward Base Pass
        Pass
        {
            Name "UniversalForward"
            Tags { "LightMode" = "UniversalForward" }

            Cull [_M_CullMode]
            Blend [_M_SrcBlend] [_M_DstBlend]
            ZWrite [_M_ZWrite]
            ZTest LEqual
            BlendOp Add, Max
            AlphaToMask [_M_AlphaToMask]

            HLSLPROGRAM
            #pragma target 3.0

            // Unity defined keywords
            #pragma multi_compile_fwdbase nolightmap nodynlightmap nodirlightmap novertexlight
            #pragma multi_compile_fog
            #pragma multi_compile_instancing

            #pragma multi_compile __ _ALPHATEST_ON _ALPHABLEND_ON
            #pragma multi_compile __ _NORMALMAP
            #pragma multi_compile __ _MTOON_EMISSIVEMAP
            #pragma multi_compile __ _MTOON_RIMMAP
            #pragma multi_compile __ _MTOON_PARAMETERMAP

            // -------------------------------------
            // Universal Pipeline keywords
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
            #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
            #pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS
            #pragma multi_compile_fragment _ _SHADOWS_SOFT
            #pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
            #pragma multi_compile _ SHADOWS_SHADOWMASK
            #pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION
            
            #pragma vertex MToonVertex
            #pragma fragment MToonFragment

            #define MTOON_URP

            #include "./vrmc_materials_mtoon_forward_vertex.hlsl"
            #include "./vrmc_materials_mtoon_forward_fragment.hlsl"
            ENDHLSL
        }

        // Built-in Forward Base Pass
        Pass
        {
            Name "MToonOutline"
            Tags { "LightMode" = "MToonOutline" }

            Cull Front
            Blend [_M_SrcBlend] [_M_DstBlend]
            ZWrite [_M_ZWrite]
            ZTest LEqual
            Offset 1, 1
            BlendOp Add, Max
            AlphaToMask [_M_AlphaToMask]

            HLSLPROGRAM
            #pragma target 3.0

            // Unity defined keywords
            #pragma multi_compile_fwdbase nolightmap nodynlightmap nodirlightmap novertexlight
            #pragma multi_compile_fog
            #pragma multi_compile_instancing

            #pragma multi_compile __ _ALPHATEST_ON _ALPHABLEND_ON
            #pragma multi_compile __ _NORMALMAP
            #pragma multi_compile __ _MTOON_EMISSIVEMAP
            #pragma multi_compile __ _MTOON_RIMMAP
            #pragma multi_compile __ _MTOON_PARAMETERMAP
            #pragma multi_compile __ _MTOON_OUTLINE_WORLD _MTOON_OUTLINE_SCREEN

            #pragma vertex MToonVertex
            #pragma fragment MToonFragment

            #define MTOON_URP
            #define MTOON_PASS_OUTLINE

            #include "./vrmc_materials_mtoon_forward_vertex.hlsl"
            #include "./vrmc_materials_mtoon_forward_fragment.hlsl"
            ENDHLSL
        }

        //  Shadow rendering pass
        Pass
        {
            Name "ShadowCaster"
            Tags { "LightMode" = "ShadowCaster" }

            Cull [_M_CullMode]
            ZWrite On
            ZTest LEqual

            HLSLPROGRAM
            #pragma target 3.0

            // Unity defined keywords
            #pragma multi_compile_shadowcaster nolightmap nodynlightmap nodirlightmap novertexlight
            #pragma multi_compile_instancing

            #pragma multi_compile __ _ALPHATEST_ON _ALPHABLEND_ON

            #pragma vertex MToonShadowCasterVertex
            #pragma fragment MToonShadowCasterFragment

            #define MTOON_URP
            
            #include "./vrmc_materials_mtoon_shadowcaster_vertex.hlsl"
            #include "./vrmc_materials_mtoon_shadowcaster_fragment.hlsl"
            ENDHLSL
        }
    }

    FallBack "Hidden/Universal Render Pipeline/FallbackError"
    CustomEditor "VRMShaders.VRM10.MToon10.Editor.MToonInspector"
}