simplestarの技術ブログ

目的を書いて、思想と試行、結果と考察、そして具体的な手段を記録します。

Unity:VRMをLWRPで表示するためのマテリアル変更

VRMのシェーダーの LWRP 対応が期待されるところですが、無理やりマテリアルを置換して表示することも可能です。
ランタイムロードについては過去記事
simplestar-tech.hatenablog.com

の通りですが、LWRP 環境で表示するとピンク色(シェーダエラー色)になります。
置換する具体的な方法をここに記します。(VRMファイルによって失敗することもあります。)

foreach (var renderer in go.GetComponentsInChildren<Renderer>())
{
    bool body = 0 == string.Compare("Body", renderer.gameObject.name);
    foreach (var material in renderer.sharedMaterials)
    {
        var tex = material.mainTexture;
        var objname = renderer.transform.gameObject.name;
        bool transparent = false;
        if (!body)
        {
            foreach (var keyword in material.shaderKeywords)
            {
                if (0 == string.Compare("_ALPHABLEND_ON", keyword) || 0 == string.Compare("_ALPHATEST_ON", keyword))
                {
                    transparent = true;
                    break;
                }
            }
        }
        material.shader = transparent ? transparentShader : opaqueShader;
        var names = material.GetTexturePropertyNames();
        foreach (var name in names)
        {
            material.SetTexture(name, tex);
        }
    }
}

コード内で登場する以下の変数は、あらかじめ LWRP 用に作ったシェーダーである必要があります。
transparentShader
opaqueShader

追記:スカートや袖など衣服は TwoSide シェーダーだったので、次のようにチェックして、カリングしないシェーダーも用意して適用すると見た目の破綻が無くせました。

if(material.HasProperty("_CullMode"))
{
    var cull = material.GetFloat("_CullMode");
    if (0 == cull)
    {
        material.shader = opaqueTwoSideShader;
    }
}

なんで "_CullMode" がわかったかについてですが、オリジナルのシェーダーコードをじっと眺めるとわかります。

上記のコードあるなしの結果はこちら
要はMToonシェーダーにこだわらなければ、ひとまず表示できるようになります。

f:id:simplestar_tech:20190413180803j:plain
この絵を直すのに、このコードが必要だとイメージできればOK

追記の追記

色々とややこしくなったので、手っ取り早い対応を発見したので、最後に追記しておきます。
次のような Unlit LWRP 用シェーダーを構築して

f:id:simplestar_tech:20190413211118j:plain
Shader Graph for MToon
先ほどの複雑化したコードの代わりに次のコードでマテリアル置換するようにします。
上の Shader を opaqueTwoSideShader 変数に代入して使います。

foreach (var renderer in go.GetComponentsInChildren<Renderer>())
{
    foreach (var material in renderer.sharedMaterials)
    {
        var tex = material.mainTexture;
        material.shader = opaqueTwoSideShader;
        var names = material.GetTexturePropertyNames();
        foreach (var name in names)
        {
            material.SetTexture(name, tex);
        }
    }
}

Alpha Test などのテクスチャ繰り抜きが正しく機能することは確認できました。
ただ、髪の毛の色とかが反映されていないことに気付いて、色々いじって、すぐに解決しなかったのであきらめました。
公式に LWRP コンバート対応が入る日が近い気がしていて、これ以上は頑張らなくても良いかなと思ってます。

f:id:simplestar_tech:20190413211812j:plain
髪の毛やまつげの色が付いていない…

追記:それから三ヶ月、自分で LWRP の Toon を写経ですが、利用できるようになりました。
simplestar-tech.hatenablog.com

追記の追記の追記の追記

LWRP で MToon 表現置換する ShaderGraph を作って公開しました!
github.com