遮蔽に隠れてもオブジェクトが見えるあの表現がしたい!と思ったのでやり方をまとめます。 (オクルージョン処理させない、みたいな表現が適切なんでしょうか)
具体的にどんな表現かといいますと、Apexのブラッドハウンドの戦術アビリティのような所謂"ウォールハック"の表現です。
このような表現が、ゲームでは多々見られます。
これまでこのような表現をするためにはShaderを自分で書いていたかと思います。
しかし、SRPの登場により、レンダーパイプラインを修正することで実現可能になりました。 (もしかしたら昔からShaderなしで実現できたのかもしれませんが・・Unity素人なのでその辺りはわかりません・・)
実装方法
※URP環境下での例になります
シチュエーション
適当にそれっぽいマップを用意します
コンテナの後ろには兵士が隠れています。
この兵士コンテナ越しでも見えるようにしていきましょう。
手順
(1) Layerを追加し、モデルのレイヤーを変更する
透過対象のオブジェクト(今回だと兵士のモデル)に設定するレイヤーを追加しておきます。
今回は「WallHackTarget」レイヤーを追加してみました。
兵士用のモデルのレイヤーをこのレイヤーに変更しておきます
(2)RendererのOpaque Layer Maskの設定を修正
URPに設定されているRendererの設定を修正していきます。 (デフォルトだと"UniversalRenderPipelineAsset_Renderer")
まずは"Filtering"→"Opaque Layer Mask"を選択し、WallHackTargerレイヤーのチェックを外します。
Opaque Layer Maskの名前の通り、ここでチェックがついているレイヤーのみ不透明になりますので、チェックを外したことによってこのレイヤーが透明になります。
よって、兵士がカメラに映らなくなりました。
(3)RendererのFeatureを追加していく
Renderの最下部にある"Add Renderer Feature"から、設定を追加していきます。
1つ目は、遮蔽越しに見えるようにするための設定です。以下のように設定します。
"After Rendering Opaques" つまり、不透明オブジェクトのレンダリングが終了した後に適用される処理になります。
Filtersも特に言及することないのですが、見た通りWallHackTargetレイヤーを不透明にしています。
このままでは、普通にモデルが表示されるだけですし、遮蔽にも隠れてしまいます。
ここで、Overridesの設定をしていきます。
ポイントは"Depth"の"Depth Test = Greater"これだけになります。
DepthTestとは、深度バッファの情報を比較してオクルージョン処理をするための設定になります。
この値によってDepthTestの実行方法を変えることができます。
デフォルトでは、ある物体の手前にあるピクセルは描画しないようにするため"LessEqual"(既に描画されてるオブジェクトと距離が等しいか、それより近い場合に描画)に設定されています。
しかし、WallHackレイヤーに限っては"Greater"(既に描画されているオブジェクトより距離が遠い場合に描画)に変更します。
こうすることで、手前に何かオブジェクトがあったとしても描画されるようになりました。ウォールハックができています。
※overrideするmaterialはよしなに設定してください
しかし、この設定だけだと当然DepthTestがGreaterの条件にマッチするときしか描画されないので、逆に手前に何もオブジェクトがない状態では表示されないままです。
そこで、最後にもう1つだけ以下のようなRendererの設定を追加します。
上記の設定で、WallHackTargetレイヤーを不透明にするようにしておきます。
Overrideの設定は何もしなくて良いです。DepthTestはデフォルトで"LessEqual"になっていますので。
これで、遮蔽がないときはふつうに表示され、遮蔽があるときは壁越しに表示される表現が完成しました!
おわりに
使用するRendererはRendererListに複数登録できますので、通常時に使うRendererとウォールハックRendererを特殊スキルを使用時などの条件で切り替えることによって、無事ゲームに組み込むことができそうです! めでたい!