Deferred Decal

ぷちコン応募作品製作のためブログの更新が滞ると思いますが、何かネタがあったら更新するかもしれません。

気長にお待ちください。

さて、今回紹介するのはUE4Deferred Decalです。

Decalというのは元はデカルコマニーと呼ばれる転写技術のことだそうです。

日本人男子ならガンプラデカールを思い浮かべるかもしれませんね。

UE4に限りませんが、ゲームのグラフィクス技術でデカールというと、弾痕、血痕といったものをステージモデルやアクターモデルなんかに貼りつける技術を指します。

初代『Halo』の日本発売時CMでは、壁に弾痕で"X"を書くということをしていましたが、ここで使用されているのがデカールです。

デカールは基本的に、ある一定範囲内に任意の方向からテクスチャを投影する、という手法をとります。

ただし、実装方法はいくつか存在しています。

昔、PS2のあるゲームで足跡を実装したときは、コリジョンモデルに対して投影するテクスチャを四角柱上に投影し、コリジョンモデルのポリゴンを分割して足跡モデルとして描画したことがあります。

また、デカールを貼りつけるモデルを、貼りつけられるデカール分だけ描画する、なんて方法もあります。

前者はコリジョンが描画モデルと同一でなければ浮いたり埋まったりしてしまいますし、後者はほんの一部の描画のためにモデル全体を描画するのは速度面で問題が出てきます。

前者はコリジョンモデルでなく描画モデルで実装すれば埋まったりする問題に対応できますが、描画モデルのポリゴン数によっては負荷が高くなってしまいます。

で、最近のゲームやUE4ではどうしているかというと、すでに描画されている深度バッファを利用して描画済みカラーバッファやGBufferに対してスクリーン空間で張り付けるような手法をとっているものが多いようです。

UE4はGBufferに対して貼りつけており、それゆえに"Deferred Decal"と呼ばれているようです。

シェーダコードを読むと、これでいいのか?と思う部分もありますが、まあうまくいってるっぽいのでいいか。

では、続きから使い方の解説です。

まあ、難しいことはほとんどないですが。

まず、Deferred Decalを使用する前に、Deferred Decal用のマテリアルを作成しなければなりません。

マテリアル作成は普通のマテリアルと同じですが、[Material Domain] を変更する必要があります。

ue177.jpg

このDomainは半透明マテリアルに近い形ですが、[World Position Offset] なんかは使用できません。

モデルを描画するわけではないのでこの辺の情報は使用されないんですね。

次に重要なのは [Decal Blend Mode] です。

ue178.jpg

[Decal Blend Mode] は複数存在していますが、デカールのGBufferに対するブレンド方法を指定しています。

多分、多くの人が利用するブレンド方法は上から4つのモードだと思います。[Translucent], [Stain], [Normal], [Emissive] の4つですね。

[Translucent] はBaseColorやNormal、MetallicなどのパラメータをそのままGBufferにアルファブレンドするモードです。

最も多く使われるのではないかと思うのですが、使い道としては貼り付け先のマテリアル対して無関係な質感のものをデカールするのに使用するものでしょう。

金属床に対して血痕を残すような場合は血は浸透していかないのでこのモードを使用する方がいいかと思います。

[Stain] もやはりBaseColor等をフルに設定できるのですが、こちらは [Translucent] とは逆に、何かに浸透するような場合に使用することになります。

土や布などに血痕を残したい場合は浸透することを考慮してこのモードを利用する方がよいかと思います。

[Normal], [Emissive] はそのままです。法線、もしくはエミッシブのみアルファブレンドします。

[Normal] は例えばひっかき傷なんかを表現するのにはいいかもしれませんが、本来ひっかき傷などはラフネスの値などにも変化を与えるのでこれだけで対処するのはあまりよろしくないかもしれません。

[Emissive] は蛍光塗料ぐらいしか使い道は考えられませんが、ライトを当てたところに文字が浮かび上がる、とかの表現では使えるかもしれませんね。

マテリアルを作成したらデカールを貼りつけます。

アクター選択から [Deferred Decal] を選択し、Level Editorに配置しましょう。

そして、このマテリアルに先に作成したデカールマテリアルを設定すればOKです。

ue179.jpg

実際に貼りつけた画像はこんな感じ。

ue180.jpg

エディタ上ではデカールの貼りつけ方向が矢印で表現されてわかりやすいですね。

デカールは通常、どんなオブジェクトにも自動的に貼りつけられるのですが、上図では左の赤いオブジェクトに対して貼りつけられていません。

デカールが貼りつけられるかどうかはモデルの [Rendering] 設定にデカールされるかどうかの設定が存在します。

ue181.jpg

デフォルトはONですが、図のようにOFFにするとデカールが無効になります。

[Decal Blend Mode] の違いは以下の図を見てもらえればわかりやすいかと思います。

左から [Translucent], [Stain], [Normal] です。

ue182.jpg

デカールを貼りつける際の注意点ですが、貼りつける方向は特に注意してください。

デカールは指定範囲内には無条件に貼りつけされるのですが、モデルの法線方向などは見ません。

なので、指定範囲内に入っていれば貼りつけ方向の”後ろ”側でも貼りつけられます。

問題は、その場合に法線方向がおかしくなってしまうことです。

ue183.jpg

見ての通り、法線方向が逆転してしまっているのがわかります。

もう1つの問題は貼りつけ方向に対して水平のポリゴンに対しては伸びるような映像になってしまう点です。

ue184.jpg

貼りつけ範囲の奥行きを小さくすれば目立たなくはなりますが、貼りつけられて欲しい部分に正常に貼りつかないなどの問題も発生します。

レベルエディタで貼り付けを行うのであれば調整もしやすいのですが、インタラクティブな動作に対して動的に貼り付ける場合はいろいろ工夫しないといけないでしょうね。

小さいもの(弾痕とか)ならそこまで難しくはないでしょうけど、広い範囲で血痕を残すような場合は単純にはいかないでしょう。

最後にDBufferについて解説します。

先のブレンド方法で、法線と一緒にラフネスなども変更した方がよい、という話をしました。

しかし、先に紹介した4種類のブレンド方法では、例えばカラーのみ、法線とラフネスのみといったブレンドは不可能です。

これはGBufferに複数の情報がエンコードされて格納されているためで、通常のブレンド方法ではこの辺をうまく選択して対応することができません。

OpenGLは最新バージョンでブレンド方法のプログラマブル化(つまり、シェーダコードのような手法でブレンド方法を記述できる)機能が存在していますが、DX11やOpenGLESには存在していません。

そのため、UE4ではDBufferという機能が存在しています。

DBufferはデフォルトでは無効になっています。

この機能を利用するとどうしてもDrawCall数が増えてしまい、シーンの複雑さによっては非常に大きな問題になります。

通常の描画パスは簡略化すると以下のようになります。

 1.不透明オブジェクト描画(深度バッファ、GBufferの描画)

 2.デカールのGBuffer描画(Translucent, Stainなど)

 3.ライティング

このようにデカールの情報はGBufferに直接描画されます。

これに対してDBufferはデカール用の特殊なバッファで、GBufferとは別に描画されます。

不透明オブジェクトを描画する際、あらかじめ描画されているDBufferの内容を加味してGBufferへの書き込みを行う、というのがDBufferを利用した際の描画パスです。

以下がDBuffer利用時のパスを簡略化したものです。

 1.不透明オブジェクトのZ Pre-pass描画(深度バッファのみ描画)

 2.DBufferへのデカール描画(深度バッファを利用指定座標を求める)

 3.不透明オブジェクト描画(GBufferへの描画、DBufferの内容をブレンドする)

 4.デカールのGBuffer描画

 5.ライティング

パスが2つ増えます。

最初のパスは深度バッファのみを描画するZ Pre-pass描画で、デカールするのに必要な深度バッファだけ先に描画しておきます。

次にDBufferという特殊なバッファにデカールを描画します。

ここで描画した内容はこの後の不透明オブジェクトのGBuffer描画時に参照され、各種情報をブレンドされます。

不透明オブジェクトをGBufferに描画した後に普通のデカールを描画し、その後にライティングという流れは変わりません。

DBufferはデフォルトでは使用できませんので、エンジン側の設定として追加してやる必要があります。

プロジェクト単位で設定する場合は各プロジェクトフォルダの Config/DefaultEngine.ini に以下の4行を追加しましょう。

[SystemSettings]

r.EarlyZPassMovable=1

r.EarlyZPass=2

r.DBuffer=1

すべてのプロジェクトで使用したい場合は各エンジンバージョンフォルダの下の Engine/Config/BaseEngine.ini の [SystemSettings] タグに上述の設定を追加します。

初回はシェーダのビルドが走るので、シーンが複雑だと起動までに時間がかかります。

DBufferを使ったデカールを行うにはマテリアルでDBufferに描画するための設定を行います。

[Decal Blend Mode] に [DBuffer Translucent ~] という設定があるので、これを使用するとDBufferへの描画となります。

ue185.jpg

~部分はブレンドするパラメータを列挙しているだけなので、先のような法線とラフネスを設定したい場合には [DBuffer Translucent Normal Roughness] を選択します。

というわけでデカールの解説はこれでおしまい。

ちなみに、DBufferのパスについてはシェーダコードからちょっと推測してる部分もあるので、もしかしたら間違ってるかも。