UE4 内部構造が透けているように見える疑似透過シェーダ(CEDEC2018)

UE4.20.2

CEDEC2018のモンスターハンター:ワールドのシェーダ関連講演で触れられていた「疑似透過シェーダ」をUE4マテリアルでやってみる。
要するにMH:Wのストーリーラストのアイツのように内部が透けて見えるようなことをしたいというもの。

先に結論を見せると以下のようになった。



「普通の不透明な外側モデル」の内部に「疑似透過シェーダのモデル」を配置すると
内部のモデルが透けて見えるようになる。


今回UE4のマテリアルブループリントで作ってみたものを3行で説明すると

  • Translucentマテリアルで
  • 深度テスト無効で
  • SceneDepthよりPixelDepthのほうが大きい場合だけその差に応じて色を決定

以上

CEDECの講演については以下の記事の下の方。
www.famitsu.com

講演時は内部構造モデルをカメラの方に引き寄せて描画するという説明で、内部構造モデルが手前に飛び出しているような絵で説明されていた。
ただ本当に頂点操作で手前に飛び出させると色々問題がありそうなのであれはあくまでイメージで、きっと深度テストの工夫でやっていたと予想。

というわけで以下のように半分埋まった球を透けさせてみる。
f:id:nagakagachi:20180908152814p:plain

  1. 新規マテリアルを作成してメッシュにセットしておく. マテリアル名はとりあえず MAT_PseudoTranslucentTest で.
  2. マテリアルの Blend Mode を Additive に変更. Opaqueだと後述する 深度テスト無効 が使えないので.
    • f:id:nagakagachi:20180908154552p:plain
  3. マテリアルの Disable Depth Test (深度テスト無効) をONにする.
    • f:id:nagakagachi:20180908154119p:plain
  4. エミッシブに赤を入力する. 後のために乗算ノードを挟んでおく.
    • f:id:nagakagachi:20180908154827p:plain
  5. ここまででこうなる. 深度テスト無効で描いてるのだから当然.
    • f:id:nagakagachi:20180908164243p:plain
  6. 次は透過の表現のためにPixelDepthとSceneDepthの差を使ってグラデーションを計算する. PixelDepthとSceneDepthの出力はMax2048らしいので0~1の範囲にするために割っている. DepthRangeパラメータは深度差のグラデーション範囲を制御する(値は0.02). Sharpnessパラメータはグラデーションの鋭さを制御する(値は2).
    • f:id:nagakagachi:20180908164952p:plain
  7. ここまでで以下のようにメッシュが埋まっている部分が表面に近いほど色が濃いグラデーションになる.
    • f:id:nagakagachi:20180908174033p:plain
  8. PixelDepthのほうがSceneDepthのほうが手前の場合は表示しないように条件と乗算を追加.
    • f:id:nagakagachi:20180908180336p:plain
  9. 埋まってる部分だけが表示される.
    • f:id:nagakagachi:20180908180402p:plain
  10. わかりにくいので壁メッシュのマテリアルをスターターコンテンツの"M_Tech_Hex_Tile"に変えてみたところ.
    • f:id:nagakagachi:20180908181241p:plain
    • f:id:nagakagachi:20180908182758p:plain わかりやすいように位置調整.

なんとなく表面からの距離によって透過度合いが変わって透けているように見えるかな?あくまで外側は普通のOpaqueマテリアルで、内部構造側のマテリアルが透けているように見せている。
サンプルプロジェクトに入っている"MAT_PseudoTranslucent"はもう少し調整してある。

今回は深度テストを無効にして深度バッファの奥側の部分にだけ色が塗るように計算しているが、通常の深度テストとは逆のGreaterな深度テストで深度バッファの奥側だけ内部構造モデルの描画をするようにしたほうがいいと思う。UE4ではやり方がわからなかった。
また、特定の外側モデルの内部にだけ描画したい場合は外側モデルの描画時にステンシルにマーキングし、内部構造モデルの描画時のステンシルテストでマーキングされたピクセルにだけ描画するといったことが必要かも。

この方法は内部構造モデルを描画する必要があるのでパフォーマンス的な問題があるかもしれないけどいろいろ面白いことができそう。