Contents

lilToon_MsdfMask の解説・使い方

元々えろぬの用に作ってたなんて言えねえ!!

/posts/liltoon-msdfmask-instruction/liltoon-msdfmask.png
lilToon_MsdfMask で追加されるプロパティの部分

lilToon_MsdfMask は、lilToon のカスタムシェーダー機能を使って、次の機能を追加したものです。

アルファマスク 2nd

これはほぼ名前通りの機能で、すでに存在するアルファマスク(以下 1st)に上から追加でもう一枚アルファマスクを適用できるものです。 合成モードも 1st と同じく置き換え(これはあんま意味ないか)、乗算、加算、減算をサポートしています。

具体的な使用用途としては、半透明マテリアルでアルファが MainColor 側に乗っておらずアルファマスクテクスチャが別途あるような場合に追加でカットアウトマスクなどを使いたい場面などが考えられますね。 とはいえ lilToon 標準機能にアルファマスクの焼き込みがあるのでわざわざ 2nd を使う意味はそんなにないかもしれないです(1st の方を動的に変えたいなどの場合は 2nd を使うしかない)。

MSDF マスク

もう一つが(元々こっちがメインだった)主要なマスクテクスチャを MSDF として解釈するオプション。上の画像にあるとおり、マスクをかけられるかつ MSDF でかける需要がありそうなフィールドについては一通り対応しています。値の反転も可能です。

補足: MSDF について

MSDF (Multi-channel Signed Distance Field) については Chlumsky/msdfgen を参照してください。

……というのは不親切すぎるので簡単に説明すると、まず SDF (Signed Distance Field) というのが(相対的に)昔からありました。 これは GPU によるテクスチャの線形補間をうまく使うことでラスター画像であるテクスチャでベクター画像を表現する手法です。 SDF も十分便利なんですがある問題が知られていて、任意の場所で線形補間が適用されるのでベクター形状の鋭い角がなまってしまうことがあるのです。

MSDF はこれを 3 チャンネルに拡張してそれぞれの SDF の中央値をとることで、各チャンネルの角がなまらないおいしいところだけを活用できるという感じですね。 (2024-01-07: 積集合ではなく中央値が正しかったので修正、thanks to @prime)

lilToon にも MSDF テクスチャのチェックボックスあるよね?

MSDF テクスチャとして解釈するオプション自体はメインカラー 2nd/3rd にもあります。が、これはメインカラーのテクスチャを MSDF として解釈するのでそれによって切り抜かれた形状に載せられるのは tint で指定する単色背景だけです。 lilToon_MsdfMask では マスクテクスチャ側を MSDF として解釈させることで、標準ではできない単色以外の切り抜きに対応 しています。

使い方

VPM 対応済なので、VPM 経由で lilToon を導入しているならば 僕の VPM Package Repository から最新版を選んでインストールするだけで使えます(VCC 側で preview package の表示を有効化する必要があります)。

使い方は大まかには以下のような感じです。

  1. MSDF テクスチャを用意する
  2. マテリアルの使用シェーダーを MsdfMask/lilToon に変更する
    • バンドルサイズ削減のために、MSDF マスク機能の使用関係なくアバターで使うマテリアルは全部こちらに寄せた方が良い気がします
  3. カスタムプロパティーから、マスクを MSDF 化したい部分を有効化する
  4. マスクテクスチャを差し替える

MSDF テクスチャの生成について

MSDF テクスチャをどうやって用意するかですが、これも端的に言えば「単一のパスのみをもつ SVG ファイルを用意して msdfgen にポイする」ということになります。

最初にマスク画像になる SVG ファイルを作成することになりますが、これ自体は最近のベクタードローツールなら何でもいいと思います。Illustrator なり Affinity Designer なり Inkscape なり、お好みのツールで。 このとき、キャンバスのサイズをピクセル指定にして最終的に出力したい MSDF テクスチャのサイズにしておくと後々楽になります。あ、 1024px 四方とかバカでかいサイズ(この用途だとこれは本当にデカすぎる)にしなくていいですよ。大抵の場合 64px 四方で十分です。

次にパスを「単一化」しなければなりません。これは msdfgen がそれしか対応していないからなのでまあやりましょう。連結成分が複数に分かれてても問題ありません。 ブラウザ上でなら SVGOMG などが使えます。あとドローツール側に結合する機能があると思います。 Affinity Designer では、複数の図形を選択して 右クリック > ジオメトリ > カーブを結合 で単一のパスに変換できます。

最後に msdfgen で SVG を変換します。上記リポジトリの Release から実行ファイルが入手できるので、適当に展開して以下のようにコマンドを実行すると生成されます。

msdfgen.exe msdf -svg input.svg -o output.png

あとは Unity にできた PNG ファイルをインポートするだけですが、このとき Texture is sRGB のチェックを外すのとテクスチャ圧縮を無効にする のを忘れないようにしてください。さもないと出力される形状がおかしなものになります。

使用例

9 月末ごろを境に natsukitten2 のスパッツのエッジがキレッキレになったのは lilToon_MsdfMask の成果です。 (念のためデフォルトで画像を伏せています)

Before: 通常アルファマスク使用時

/posts/liltoon-msdfmask-instruction/spats-before.jpg
スパッツの裾の端がボヤけているのがわかる
このときはメインカラー 2nd に 2048px 四方の BC7 圧縮のテクスチャを入れていたので、 スパッツに対する VRAM 消費量は約 5.3MB でした。

After: MSDF マスクテクスチャ使用時

/posts/liltoon-msdfmask-instruction/spats-after.jpg
スパッツの裾の端がクッキリしている
MatCap テクスチャに 128px 四方の BC7 圧縮のテクスチャを入れて 21KB、スパッツ領域のマスク用の MSDF テクスチャが 16KB なので、 スパッツに対する VRAM 消費量は約 37KB まで一気に減りました。