31
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

NTTドコモ R&DAdvent Calendar 2021

Day 5

真っ白な空間を作る (Unreal Engine 4)

Last updated at Posted at 2021-12-04

この記事で作る世界

image.png

目指すのは、この「真っ白で何もない世界」。

映画『The Matrix』に出てきたシーンや、ジョージ・ルーカス監督のデビュー作『THX 1138』のシーンなど、SF映画でたまに目にする光景です。白いキャンバスのような空間なので何でも自由にできる可能性を感じつつ、方向感覚も見失う上に空間上に入り口も出口も存在しないため VR とかで体験を行うと頭が混乱してしまいそうな雰囲気がありますね。

周りのアクターをすべて白に設定してみると...

この世界は、周りのアクターを白く設定すれば簡単に作れそうな気がしますが、例えば Base Color を白に設定しただけだと思ったよりも白くなりません。

image.png

Emissive Color を使うことによって全体的に白くなりますが、床に影が出なくなってしまったり、周囲を囲むアクターの境界線が僅かに残ってしまう問題など、この方法も簡単にはいきません。

image.png

実装方法をネットで調べてみても、それらしき答えはぱっとは出てきません。

今回はそんな白背景の空間を、きちんと床に影を落とした立体感のある空間になるように作ってみようと思います。

作り方のポイント

作り方はいろいろな方法があると思いますが、今回はシンプルに実装しようと思い 表示したいアクターとその影の部分以外のピクセルをすべて白く塗る というアプローチを取りました。 Post Processing を使います。

鍵となるのは2点。 白く塗るピクセルをどうやって切り出すか と、 影をどうやって切り出すか

1点目については Stencil Buffer を今回使用します。 Stencil Buffer はレンダリングで使われる Color Buffer や Z Buffer と似たような形で、追加のデータを保持することができるバッファーになります。 Stencil という単語自体は下図のような中がくり抜かれたシート状のものを指しています。このシートを壁に貼り付けてスプレーを吹きかけると、下の2枚目の図ののように壁に文字を印字できます。 Unreal Engine 4 でも同様の使い勝手が可能で、ピクセルごとに処理を適用させる部分と適用させない部分を分けることができます。

PartsOfStencil.png Quadrilingual danger sign - Singapore (gabbe).jpg

Unreal Engine 4 における Stencil Buffer の例がこちら。公式のチュートリアル動画 では特定のオブジェクトに対してのみ色を残してそれ以外は desaturate する方法を説明しています。

image.png

image.png

2点目の影の切り出しについては、このあと具体的なノードの接続方法と一緒に説明します。

具体的な手順

具体的な作り方を見ていきます。今回は Unreal Engine 4.27.1 を使用しました。

Step 1. Stencil Buffer を有効にする

Stencil Buffer は Unreal Engine 4 ではデフォルトでは無効となっています。まずは有効にしましょう。

  1. プロジェクト設定を開く
    image.png

  2. 「エンジン」の「レンダリング設定」を開く
    image.png

  3. 「ポストプロセス」のところにある「カスタム深度ステンシルパス」を「Enabled with Stencil」に設定
    image.png

これで Stencil Buffer が有効になります。

Step 2. 描画したい Actor とそうでない Actor を設定する

次に、描画したい Actor とそうでない Actor を Stencil Buffer に保持するための設定を行います。

  1. 描画したい Actor を選択し
    image.png

  2. 「Render CustomDepth Pass」にチェックを入れて、「CustomDepth Stencil Value」を1にします(値は何でも良いですが、このあと設定する Post Process においてこの数値に応じて白く塗るか否か判断するので、0以外のわかりやすい数字が良いでしょうk)。
    image.png

  3. 描画したくない Actor については、とりあえず何も手を加えなくて良いです

ちなみにですが、設定した Stencil Buffer の値を可視化する方法として、以下のように表示モードを設定するとわかりやすいです。
image.png

image.png

「001」という数字が記載されているのが見て取れますが、これは Stencil Buffer の値です。

Step 3. Post Process において、Stencil Buffer の値に応じて塗り分けをする

次に、 Stencil Buffer の値に応じて白く塗るかそのままにするか色分けをする Post Process Material を作成します。

  1. Post Process 用のマテリアルを作成する

マテリアルを作成したあと、 Material Domain を Post Process に設定。
image.png

次に Blendable Location を Before Tonemapping に設定します 。文字通り Tonemapping の前にこの Post Process を実行することを意味しますが、この設定は影の切り出しやアンチエイリアシングなどに影響がするため必要となります。

またもう一点重要な点で、 Enable Stencil Test にチェックを入れ、 Not Equal 1 という条件を設定する必要があります。こうすることで、 Stencil Buffer の値が1ではないピクセルに対してこの Post Process の処理が適用されることになり、値が1のピクセルについては Post Process が影響せずそのままになります

image.png

2.ワールドに設置する

Post Process Material をワールドに設置し、 Post Process マテリアルを設定します。

image.png

なお、この時 Infinite Extent (Unbound) にチェックを入れるのを忘れないようにしましょう。

image.png

3.影の部分を切り出し、それ以外のピクセルを白く塗る

Post Process マテリアルのノードは今回、以下のように作りました。

image.png

先程説明を後回しにしていた影の切り出しの処理ですが、実はここでそれを実装しています 。「SceneTexture:BaseColor (as stored in GBuffer)」の値から「SceneTexture:PostProcessInput0」の値を引いているのが見て取れますが、この2つの描画データの差が影に相当する部分となっているため、この2つの差分を見ることによって影だけを切り取ることができます。あとは条件分岐させて白く塗りたいところだけ値を設定しています。

ちなみにですが、白く塗るピクセルは Emissive Color で値を 10 としています。この値は大きくするほど白くなっていきますが、この値を大きくすると Bloom の影響で全体的に白くなってしまったり、 Bloom を切ったとしても Motion Blur の描画結果が少し違和感のあるものになってしまうなど問題があったため、今回は値を 10 に設定しました。

これで大体求めている結果になります。

image.png

少し全体的に黒みがかっていてコントラストは低い状態となっていますが、このあたりはワールドに設置した Post Process Volume の設定(Bloom や露出、コントラストなど)を変える事によって調整ができると思います。今回私は

  • Bloom は強度を0に設定して白っぽくならないように設定
  • 露出補正の値は 2 に設定
  • 最大輝度は 6.0 に設定

として、この記事の最初の画像のような世界を作成しました。

image.png

遊んでみる

これで真っ白な空間の完成です。コンセプチュアルな空間なので、いろんなものを配置するだけでなんだか抽象的な空間に仕上がってなかなかいい空間です。

image.png

paikroom.gif

image.png

image.png

image.png

NG パターン

最後に一点だけ補足。今回 Stencil Buffer を使ってピクセルを白く塗りましたが、この処理 (Post Processing) を After Tonemapping で実行すると、背景は完全な白になってくれるというメリットがえられるのですが、その一方で影の切り出しが難しくなります。これは、 Tonemapping の影響で、影の切り出しに使っていた「SceneTexture:PostProcessInput0」の値が変化してしまい、「SceneTexture:BaseColor (as stored in GBuffer)」との差分が大きくなってしまうことが原因です。実際、今回の場合でそれを行ってみると、床の色が若干変化してしまった影響で床がそのまま表示されてしまいます。

image.png

それならばと思い、色に対して閾値を設定して、ある色よりも白いピクセルは全部白く塗るという設定を加えてみます。そうすると今度は エイリアスの問題が発生してしまいます (実は影の切り出しとも関係してきてこのあたりの設定は少しややこしくなります)。

image.png

実際にプレーをしてみるとわかるのですが、エイリアスが汚いという問題以前に画面がかなりチラついてしまい、体験として非常に悪いものとなってしまいました。そのためこの方法は、文字通り白の背景が得られるもののあまりオススメができません。

31
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?