VRoidのモデルのマテリアルをURP対応のマテリアルに変更してみた

初投稿になります、Carnaiteと申します。
VRoid Studioが配信されてから、私はUnityで使用したり、DXLibで使用したりしました。DXLibで使用した話は今度しますね。

# VRoidをUnityで使いたい
今回はUnityで使用した話です。
Unityには結構前（覚えてない）にUniversal Render Pipeline（URP）というものが追加されました。これはLightWeight Render Pipeline（LWRP）の後継バージョンになります。
普通にUnityでプロジェクトを作成した場合はVRMに入っているMToonが使えるのですが、URPの場合、MToonが使えません。

なので、今回はVRoidのマテリアルで使用されているシェーダーをURPのLitシェーダーとURP版のUnityちゃんトゥーンシェーダーに変換するエディタ拡張を作ってみたのでそれを解説したいと思います。

# GitHubのリンク
とりまGitHubにあげましたのでリンクを。
https://github.com/Carnaite0224/VRoidMaterialChanger

# 使いかた
まず、使い方ですが、プロジェクトにUnityちゃんのトゥーンシェーダーとUniVRM、今回作成したスクリプトをインポートしてください。その後、ロードしたVRoidのモデルを選択してから、メニューバーにある、**「URP/VRoid/Materials Initialize To Lit Shader」**でLitシェーダーに、**「URP/VRoid/Materials Initialize To Toon Shader」**でUnityちゃんトゥーンシェーダーに変換出来ます。
取り合えず、MToonから変換することを前提にしているのでLitシェーダーとトゥーンシェーダーでの相互変換には対応していません。

そして、スクリプトについてですが、行っていることは変換後のマテリアルに必要な情報を保持しておいて、シェーダーを変更した後に設定を行うだけです。ただ、どれが最低限必要なのかを調べ、実装をしてみました。

### MToon→Litシェーダー
まず、Litシェーダーですが、必要なものは少なかったです。（そもそも把握しきれていない。）なので、これだけで済みました。

```
 baseMap = material.GetTexture("_MainTex");
           normal = material.GetTexture("_BumpMap");
           emittive = material.GetTexture("_EmissionMap");
           color = material.GetColor("_Color");

       material.SetTexture("_BaseMap", baseMap);
       material.SetTexture("_BumpMap", normal);
       material.SetTexture("_EmissionMap", emittive);
       material.SetColor("_Color", color);
       material.SetFloat("_AlphaClip", 1.0f);
```

重要なことは特にないです。ただ、**_AlphaClip**の設定だけ行わないとだめでした。

### MToon→Unityちゃんトゥーンシェーダー
次にUnityちゃんトゥーンシェーダーです。こっちの方が設定が大変でした。シェーダーの表示にエディタ拡張が使われているので、エディタ拡張までしっかり読みました。

```
baseMap = material.GetTexture("_MainTex");
           shadeTex = material.GetTexture("_ShadeTexture");
           normal = material.GetTexture("_BumpMap");
           emittive = material.GetTexture("_EmissionMap");
           color = material.GetColor("_Color");
           shade = material.GetColor("_ShadeColor");

 material.SetTexture("_BaseMap", baseMap);
       material.SetTexture("_1st_ShadeMap", shadeTex);
       material.SetTexture("_NormalMap", normal);
       material.SetTexture("_EmissionMap", emittive);
       material.SetColor("_BaseColor", color);
       material.SetColor("_1st_ShadeColor", shade);
       material.SetInt("_CullMode", 2);
       material.SetInt("_ClippingMode", 2);
       material.SetFloat("_IsBaseMapAlphaAsClippingMask", 1.0f);
       material.SetFloat("Tweak_transparency", 0.0f);
       material.SetFloat("_Is_BlendBaseColor", 1.0f);
```

まず、取得するパラメータについては**_ShadeColor**が必要です。トゥーンシェーダーにも同じ名前の変数があるからこれであっていると思います。
あとは設定なのですが、ここが一番大変です。
まず、ベースマップや法線マップは同じなのですが、カリングの設定や透明処理の問題、アウトラインの設定をする必要があります。
**_CullMode**と**_ClippingMode**がカリングの設定です。これはEnumです。
**_IsBaseMapAlphaAsClippingMask**と**Tweak_transparency**は透明度の設定です。ここがエディタ拡張によるものだったので、解析が大変でした。
**_Is_BlendBaseColor**がアウトラインの設定です。

# 1つだけ分からないバグが...
変換は今回紹介したソースコードで出来ました。ただ、1つだけバグなのか知らないのか分かりませんが、バグがありました。
それは、一度エディタ上でマテリアルを選択しないと描画に反映されないことです。なぜ...？
エディタ上を更新しても選択オブジェクトにマテリアルを設定してもダメでした。これだけは本当に分からないので、分かるお方がいらっしゃいましたらご教授お願い致します。
![iv7yz-qebbc.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1221815/ffd6cfe6-e135-f67a-4d13-78a194d1690d.gif)


# 最後に
正直、友達には「FBXに変換してから使った方が軽いからいいよ」って言われたけど、髪が揺れるし、使ってみたかったんですよ。今回作った機能を使ってVRoidのキャラクターで何かゲーム作ってみたいですね。VRoidのキャラクターをBlenderで少し改変することも考えてますし、これからも色々やってみようと思います。