ステンシル周りの情報があまりネット上に転がっていないので、自分で色々検証して得た知見をここにメモしていこうと思います。
環境
- Windows10または11
- UE5.3
モデルはゼンゼロのMMDモデルを使用させていただいております。
Stencilの付け方
まずは基本から。
プロジェクト設定より、カスタム深度ステンシルパスを「Enable with Stencil」に変更する。
- ステンシルを割り当てたいオブジェクトを選択
- 詳細パネルの検索欄に「custom」を入力
- 「Render CustomDepth Pass」にチェック
- 「CustomDepth Stencil Value」に0以外の数値を入力
- 特に理由がなければ「Custom Depth Stencil Write Mask」をdefaultに設定
↓ステンシルの状態はビューポートの左上表示設定の「バッファを可視化」「カスタムステンシル」より確認できる。
ポストプロセスのSceneTextureでStencilの値ごとにマスクとして取得できます。
以下の画像は1以上の値は全部真っ白になってしまうので、10分の1にして出力したもになります。
Stencil値は左から2,4,6,8,10
出力結果は左から0.2,0.4,0.6,0.8,1.0
特定のステンシル値を取得したい場合は以下のように、指定した値だけ通すようにすればOKです
異なるStencil値の交差する部分を取得する
見出しの通り 異なるStencil値の交差を取得していきますが、キャラクター内で使う場合においては安定しない可能性があります。(ワールド全体でキャラクターを見た時、深度差があまりにも小さいため?)
後に紹介するやり方で、できる限り安定するように設定を詰めたつもりですが、それでも思い通りに描画されない事が稀にあります。
それを踏まえたうえで読み進めていただきたいです。
Stencil値の交差する部分を取得すると、何ができるか?
例えば、前髪に隠れた眉毛を擬似的に透けさせる事ができるようになります。
これ以外にもやり方はありますが、かなりややこしい処理が必要になるため、楽に実装したい場合はこのやり方が良いと思います。
ステンシル値を別々に割り当てる場合、コンポーネントを別々にする必要があります。
そのためキャラクターの場合、モジュール化する前提で作成しておく必要があります。
公式のドキュメントを参考にすればすぐ対応できます。
Stencilの交差を取りたいメッシュをそれぞれ別のコンポーネントとして実装します。
レベルやBPなどに配置しないとステンシルの値が設定できないので気をつけてください
「前髪」「眉毛・まつ毛」の交差を取得したいので、
「前髪」「眉毛・まつ毛」「その他」にコンポーネント(スケルタルメッシュ)を分けます。
- 「その他」のコンポーネントを選択して、詳細タブの検索欄に「custom」と入力
- 「CustomDepth Stencil Value」を適当な値に設定。例では10(この数値をつける際には気をつけなければならない点があります。これについては後で紹介します。)
- 「Custom Depth Stencil Write Mask」をdefaultに設定
- 「眉毛・まつ毛」のコンポーネントを選択して、詳細タブの検索欄に「custom」と入力
- 「CustomDepth Stencil Value」を「その他」に被らないように適当な値に設定。例では2(この数値をつける際には気をつけなければならない点があります。これについては後で紹介します。)
- 「Custom Depth Stencil Write Mask」をdefaultに設定
- 「前髪」のコンポーネントを選択して、詳細タブの検索欄に「custom」と入力
- 「Custom Depth Stencil Write Mask」を「First bit(1)」~「Eighth bit(128)」のいずれかに設定。例では「First bit」
- 「CustomDepth Stencil Value」を「Custom Depth Stencil Write Mask」で設定したビットの括弧内の数値を入力。例では「First bit(1)」なので1を入力
設定が完了したので、Stencilを確認してみましょう。
すると画像のように「眉毛・まつ毛」「その他」のStencil値に
「前髪」と交差する部分のStencil値「1」が足されているのがわかります。
この現象は2進数で見ると理解できます。
「前髪」で設定した「First bit(1)」は、8ビットあるうちの一桁目に「1」を代入する事を意味します。
「その他」はStencil値が「10」なので、2進数で「00001010」となり、これの一桁目に「1」を代入すると以下のようになります。
「00001010(10)」←「00000001(1)」=「00001011(11)」
別のパターンで、「前髪」が「Sixth bit(32)」だった場合も見てみましょう。
これは6桁目に1を代入するので、以下のようになります。
「00001010(10)」←「00100000(32)」=「00101010(42)」
2進数で見た時、代入する桁に既に1が入っていると数値は変化しません。これは、足し算ではなく”代入”なので、1に1を代入しても1のままだからです。
少しややこしいですが、これで無事に交差部分(例ではStencil値「3」)を取ることができました。
交差部分のStencil値をポストプロセスでマスクとして取得し、アウトライン処理をかけたものが以下の画像になります。
実はこれだけだと…
前後関係が奥から順に
「その他」→「眉毛・まつ毛」→「前髪」の時だけ透過してほしいのに、
「前髪」→「その他」→「眉毛・まつ毛」と重なる場合も、透過されることになってしまいます。
これは「前髪」のStencilが深度、つまり前後関係の情報を持っていないために発生します。
ですが深度情報を持った「その他」や「眉毛・まつ毛」に別途頂点カラーなどでマスクしてあげれば、意図しない透過を防ぐことができます。
これはあくまで”擬似的”に透けさせるやり方です。
眉毛・まつ毛のテクスチャ色をそのまま透けさせたい場合は、このやり方だけでは不可能です。
いずれテクスチャをそのまま透けさせる方法も書こうかなと思います。
Stencilの表示がチラつくなど安定しない時の対処法
プロジェクト設定がデフォルトの状態だと、Stencilの前後関係がおかしくなる場合が多いです。
以下のように設定すると、ある程度は安定すると思います。(当社比)
- プロジェクト設定を開き、検索欄に「depth」と入力
「TemporalAA Jitterを含むカスタム深度」をオフ(場合によって深度が不安定になるので、オンのままがいいかも…)- 「深度のみのインデックスバッファをサポート」をオフ
Stencilの交差をさせる時の注意点
ステンシルの表示は、コンポーネントのマテリアルの設定によって表示されたりされなかったりします。
特に交差部分については、
マテリアルの詳細タブの「Shading Model」が「default Lit」
「Blend Mode」が「Masked」になっていると、表示されないことがあります。
「Subsurface」で「Masked」の時は何故か表示される…
こればかりは安定する設定を自分で検証する必要がありそう…
コメント