MINGTOONオープンベータ
← 一覧へ

MingToonの開発 — シェーダー実験をひとつにまとめる

私はWarudoやバーチャルアバター向け3Dアプリケーションで、長い間キャラクターシェーディングに取り組んできました。

MingToonシェーディングで描画したアバターの例
Raming ( ´∀` )b (@kim_raming)、アバターモデル: BOOTH item 6571299

私はWarudoやバーチャルアバター向け3Dアプリケーションで、長い間キャラクターシェーディングに取り組んできました。

成果はXにもよく投稿しています。その多くは製品発表ではなく、その時々に探っていた顔の影、逆光に反応するリム、MatCap表現、深度ベースのシェーディングを短く記録したものです。

なかでも、私は何度も影へ戻ってきます。

顔を横切る影は、どこまで進めば魅力を保てるのでしょう。柔らかな遷移と意図的に描いたような遷移は何が違うのでしょう。逆光のとき、顔と体が背景に溶け込まないためには、どの光を残すべきでしょうか。

実際のプロジェクトで既存のトゥーンシェーダーを数多く使い、より具体的な要件には小さなシェーダーも書いてきました。その中で、好きな点と変えたい点が積み重なりました。

顔の陰影は美しくても、影ごとの色や合成順を分けにくいシェーダーがありました。MatCapとリムライトは優秀でも、距離や画角で大きく変わるものもありました。深度効果は管理されたシーンでは美しくても、自己遮蔽やホストカメラの制約で実際のキャラクターには使いにくいことがありました。

やがて、別々に作り試してきた技法を一か所で組み合わせたいと思いました。

そのプロジェクトがMingToonです。

MingToonのマテリアル比較

アバターモデル: https://booth.pm/ko/items/6571299

私の方法だけが唯一の正解だとは考えていません

私はキャリアの大半をVRChatで過ごしたわけではありません。

主な経験はWarudoなどの3Dバーチャルアバター用アプリケーションです。MingToonは、そこで開発した手法をより多くのVRChatクリエイターにも試せる形へ移したいという思いから始まりました。

VRChatにはすでに優れた広く使われるトゥーンシェーダーがあります。MingToonをすべての代替品や万能の答えとして提示するつもりはありません。

最も軽く速いシェーダーだとも決めつけません。

必要なのが一つの明確なルックだけなら、専用の小さなシェーダーの方が速く、理解しやすく、保守もしやすいでしょう。私もその理由で多くの小さなシェーダーを書きました。

MingToonが扱うのは別の問題です。

さまざまなプロジェクトで美しいと感じた技法と、繰り返し欲しいと思った道具を集め、便利に組み合わせたいのです。機能を増やすだけでなく、互いに争わず一つのルックとして働かせることが目標です。

中心にあるのは影の設計、光の方向への反応、カメラ深度の効果です。

すべての影を同じ暗い色で終わらせたくありませんでした

トゥーンシェーダーの影は、単に光が少ない領域ではありません。

顔や体の立体感を整理し、イラストの色設計にもなります。物理的な照明より線画や色付きの線に近い役割を持つこともあります。

そのためMingToonは、すべての影を一つの暗い値として扱いません。

別々の色を与えた影が暗部で重なっただけで一色に潰れてはなりません。MingToonはマスクと色を分離し、意図した順序で合成します。

共有する影の境界にも色、幅、強さ、ぼかしを設定し、自然な遷移、色付きの縁、繊細な線画として使えます。

ハーフトーンや印刷風のShadow Patternもあります。色テクスチャを重ねるのではなく閾値場として働き、暗くなるほど点や線が育ってスクリーントーンに近い反応を作ります。

物理的な厳密さより、影がキャラクターを美しく整理することを優先します。

ベースからForm Shadowと2D Rimまで重なる過程

ベース、Form Shadow、2D Shadow、逆光反応型2D Rim Lightを独立して加え、元のテクスチャを描き直さず立体感、深度、輪郭光を整えます。

陰影が深くなるほど成長するShadow Pattern

模様は色テクスチャではなく影の閾値なので、陰影が深まるほど形が大きくなります。

逆光で強くなるRimLight

リムライトを一定の強さで輪郭に貼った装飾にはしたくありませんでした。

強い正面光では表面がすでに明るく、強いリムは輪郭を不必要に騒がしくします。

逆光では顔と体が暗く背景に埋もれるため、強い輪郭光が最も役立ちます。

そこで2D Rimは、深度の不連続を表示するだけではありません。

深度由来の輪郭マスクに光方向と逆光量を組み合わせ、光が背後へ回るほど強く、正面では控えめになります。

追加ライトも方向と色でリムに影響します。一つのメインライトに固定せず、周囲の照明へ反応させました。

画面上のリム幅も重要でした。

顔のアップ用のリムは全身で消えたり、画角が変わると太くなりすぎたりします。MingToonは2D RimとFresnel効果に距離・投影補正を行います。

正確なワールド幅ではなく、構図の変化で見える範囲が激変しないことが目標です。

影の中に残る光

逆光を扱ううち、輪郭だけでなく影の内部にも制御した光を残したくなりました。

影側が一色に潰れると顔と体の構造が消えますが、影全体を明るくすると逆光の魅力である対比が弱まります。

そこでShadow Interior Reflectionを作りました。

固定色を足すのではなく、メインライトの方向と色、環境光、追加ライトに反応してシーンとともに変化します。

物理的に正確な間接光ではなく、実際の照明情報を借りてアニメ調キャラクターの影に必要な形と色を残す道具です。

Rim Shade、Fresnel Rim、2D Rim、Shadow Interior Reflectionはそれぞれ異なる役割を持ちます。

Rim Shadeは輪郭を暗く整理し、Fresnel Rimは視点依存の光を作り、2D Rimは深度と光方向を結び、Shadow Interior Reflectionは暗部の形を保ちます。

一つの式ですべてを解くより、役割を分けて必要に応じて組み合わせます。

深度をイラストの道具として使う

深度効果は小さな付加機能ではなく、MingToonの主要テーマです。

カメラ深度は遮蔽やポスト処理だけでなく、キャラクターの形を描き直す材料になります。

主な機能は2D Rim、2D Shadow、Inner Outlineです。

2D Rimは周囲との深度差から輪郭を見つけ、照明と逆光反応を組み合わせます。

2D Shadowは現在面とずらした深度サンプルを比較し、前髪、装飾、近接物の様式化された影を作ります。

Inner Outlineは見える深度変化を追い、通常のハルアウトラインが捉えにくい薄い平面の縁を描きます。

最大の難題は自己遮蔽です。

敏感すぎると顔の微細な変化や重なったメッシュまで遮蔽物になり、同一面を強く除外しすぎると前髪の有用な影まで消えます。

そこで一つの深度差だけでなく、受光面、距離反応、同一面の可能性、顔用の安定化を考慮します。

近い遮蔽物は強く、遠いものは徐々に薄く影を落とし、制御不能な自己遮蔽で顔を汚さない動作を目指します。

色付き境界も深度サンプルを増やさず、計算済みの影の範囲から得ます。

通常のシャドウマップの代替ではなく、リアルタイムのCast Shadowだけでは難しい表現のための道具です。

投影影とリムに使うカメラ深度

カメラ深度を投影影、光反応型リム、イラスト風の線を描くデータとして使います。

水平にも垂直にも反応する4チャンネルFace SDF

顔の影の形とタイミングも直接制御したいと考えました。

幾何法線だけでは鼻や眼窩、細かな凹凸が意図した絵より複雑になります。専用の顔法線はモデルごとの準備が必要で、別のホストでは同じ動作にならない場合があります。

そこで顔のアートディレクションにはFace SDFを使います。

多くのFace SDFは左右の光が中心で、上下へ動く光にはほとんど反応しません。

MingToonは左、右、上、下を一枚のRGBAチャンネルに格納します。

頭を基準に光方向を計算して4チャンネルを混ぜるため、水平だけでなく垂直の移動にも反応します。

SDFは完成した影画像ではなく、顔の各領域がいつ影に入り、どれだけ長く明るさを保つかを示す地図です。

光方向で鼻の片側が早く暗くなり、最暗部にも小さな反射光を残せます。頬は中間調まで明るく、顔全体が影になる時に消せます。

基本陰影、鼻、頬、唇、眼窩を別レイヤーにし、拡大率、位置、反転、柔らかさ、タイミングを調整して4チャンネルへ合成します。

モデル正面から専用Face SDF UVも生成し、元の顔UVへの依存を減らします。

編集中は複数の画像とレイヤーを使いますが、完成シェーダーは合成済みの一枚だけを参照し、ランタイムスクリプトも不要です。

Face SDFのシェーディングプレビュー

Face SDFは水平と垂直に反応します。鼻や頬のレイヤーはデカールではなく、その部位が影へ出入りする時点を制御します。

モデルごとに顔UV全体を作り直さないために

モデルごとに異なる顔UV配置も解決する必要がありました。

顔、眉、まつ毛、目周辺が別々のUVアイランドにあると、正面では連続して見えても元のUVで読むSDFは境界ごとに途切れます。

制作ツールはUnityシーンの正面から新しいFace SDF UVチャンネルを生成します。

元の顔テクスチャUVは変えず、正面投影座標を未使用の別チャンネルへ書きます。元の配置で離れた部位も一つの連続座標を共有できます。

モデル上で見ながらレイヤーの位置と大きさを調整し、編集後にレイヤーとUVを最終Face SDFへ渡します。

顔パーツを一つの座標系へ置く別UV

元のUVを保ち、別の正面投影チャンネルで離れた顔パーツを一つのFace SDF座標系へ配置します。

モデル上で確認するFace SDF制作レイヤー

顔の細部を別レイヤーで調整しモデル上で確認します。最終ベイクは一枚の4チャンネルSDFへ合成します。

ハルアウトラインが逃す平面のためのInner Outline

アウトラインを最後に足す黒線ではなく、最終的な色と陰影の一部にしたいと考えました。

MingToonはHull OutlineとInner Outlineを組み合わせます。

Hull Outlineはメッシュを膨らませ裏面を描くため、頭、体、衣服など立体物の外周を安定して定義します。

しかし、すべての部位が立体とは限りません。

ヘアカード、まつ毛、リボン、装飾、一部の衣服は一枚の平面です。ハル方式では望む縁が出なかったり、見える形に沿えなかったりします。

Inner Outlineはカメラ深度でその隙間を補います。

名前に反して内部境界だけではなく、深度変化と輪郭を追い、薄い平面の縁も描きます。

平面の髪先や薄い装飾をたどり、顔、前髪、衣服の重なりも線画のように整理します。

Hull Outlineは立体物の大きく安定した輪郭、Inner Outlineは平面や小さな重なりの細線を担当します。

両方を使えば大きな輪郭を保ちつつ、ヘアカード、リボン、薄い形を補えます。

線色は固定の黒ではなくベース色と最終陰影を継承し、明部と暗部の線を現在のパレットになじませられます。

さらに別の色とブレンドを重ね、柔らかな色線から強いコミック調まで表現できます。

Hull OutlineとInner Outlineの比較

Hull Outlineは立体物の輪郭を安定させ、Inner Outlineはハルが逃す平面の髪や薄い装飾の縁を復元します。

多様なキャラクターシェーディングを一か所へ

キャラクターマテリアル制作で頻繁に使う表面機能も含みます。

ベーステクスチャとアルファマスク、最大10層のテクスチャ、5層の法線、5層のMatCapに対応します。AO、Emission、Metallic/Specular PBR、複数の色ブレンドを同じシステムで組み合わせられます。

すべてのマテリアルで全機能を有効にする意図はありません。

肌、髪、布、金属装飾には異なる処理が必要です。種類ごとに別シェーダーを作らず、一つの制作環境から選べるようにします。

機能が増えるにつれInspectorもコードと同じくらい重要になりました。

Simpleは頻出項目、Fullは全レイヤーと詳細設定、Bulkは複数マテリアルの共通設定を編集します。検索、ローカライズ、プリセット、モジュール切替、プロパティごとのリセットも備えます。

一般的なテクスチャ、色、マスク、法線、MatCapを編集可能なMingToonマテリアルへ移す変換経路も作っています。

異なる照明モデルで数学的に同じピクセルを作るのではなく、変換後にゼロから作り直さずに済む出発点を提供します。

編集時はすべての機能を、実行時は必要なものだけを

多くのモジュールを持つ制作シェーダーは、一つの効果専用の小さなシェーダーほど単純にはなりません。

そこで編集と実行の目標を分けました。

編集シェーダーは常にフル版で、ファイルを切り替えず全モジュールを使えます。

完成前にベイクがマテリアルを解析し、実際に必要になり得る機能だけを持つシェーダーを生成します。

強度0の深度効果はサンプリング前に終了し、寄与しない追加光は高価な処理前に除外します。反復値を共有し、未使用モジュールとレイヤー数はソースから削除できます。

AnimationClipとAnimatorの参照も調べます。現在無効でもアニメーションで有効になる機能は動的依存として残します。

VRChatではカスタムランタイムMonoBehaviourに依存しない完成アバターを目指します。UnityツールはUV生成、合成、解析を行いますが、結果はベイク済みシェーダー、マテリアル、テクスチャです。

Warudo無料版でも使えるようにします。ただし配信や収益活動に使われるWarudoは、個人の非商用利用と自動的に同じ扱いにはできません。

便利なルック制作のためのシェーダーであり、常に最速という主張ではありません

編集シェーダーには多くの機能があるため、すべての小型専用シェーダーより速いとは言えません。

代わりに、意図する見た目を損なわず省ける処理を最適化します。

強度0なら深度を読む前に終わり、寄与しない光は高価な経路前に省きます。深度・照明計算を共有し、標準アウトラインは不要な接空間処理を避けます。

それでもソース削減をそのまま普遍的なFPSの主張にはしません。

性能は形状、透明、オーバードロー、光とカメラの数、GPUに左右されます。同条件で再現できる比較までは最速と説明しません。

限定された一つのルックなら短い専用シェーダーが適するでしょう。多くの技法をさまざまなキャラクターで組み合わせるなら、完全な制作環境から縮小ベイクする方が便利です。

MingToonは後者のために作っています。

ほかの人が作るものを見てみたい

MingToonが準備できたら、明確な個人・非商用利用には無料で配布する予定です。

Warudoなどで使ってきた手法が、多様なVRChatキャラクターでどう解釈されるかを見たいからです。

Xへの投稿を通じ、同じ機能でも顔、テクスチャ、配色、照明、作者によって全く違う印象になると何度も感じました。

私の少数のデモだけより、多くのクリエイターが自分のアバターと好みに合わせる姿を見たいのです。

色付きの影境界を線画にする人も、逆光型2D Rimを代表的なルックにする人もいるでしょう。4チャンネルFace SDFからも想像しなかった表現が生まれるかもしれません。

その結果と意外な使い方から学び、実プロジェクトで分かった弱点をMingToonへ戻したいと思います。

Warudoでの配信や収益化放送は商用活動と結びつくため、無料の個人非商用利用とは別に定義する予定です。

MingToonは長年VRChatアバターを作った経験の総括ではありません。

Warudoなどで探ってきた影、逆光、深度の技法をVRChatでも使える形へ運ぶ試みに近いものです。

私の選択がすべてのキャラクターへの正解とは限らず、すべての案件で最小・最速でもないでしょう。

多くのトゥーンシェーダーを使い作る中で美しいと感じた技法、とりわけ影、逆光、カメラ深度を一つにまとめ、便利に組み合わせたいのです。

かつてXへ一つずつ投稿していたシェーダー実験が、少しずつ一つのシステムになっています。


原文: Raming ( ´∀` )b (@kim_raming)、Xで見る。

アバターモデル: BOOTH item 6571299。

原文 ↗