オススメ機能
Twitter
お気に入り
記事履歴
ランキング
4Gamer.net
お気に入りタイトル/ワード

タイトル/ワード名(記事数)

最近記事を読んだタイトル/ワード

タイトル/ワード名(記事数)

LINEで4Gamerアカウントを登録
QRコードでLINEの4Gamer
アカウントを友達登録すると
月〜金の週5回,21時に厳選
ニュースをお届けします!
※購読にはLINEアプリが必要です
[CEDEC 2016]UE4を扱うアーティストがつまづき易いポイントはここだ。Epic Gamesが解説する注意点と回避法
特集記事一覧
注目のレビュー
注目のムービー
印刷2016/08/31 00:00

イベント

[CEDEC 2016]UE4を扱うアーティストがつまづき易いポイントはここだ。Epic Gamesが解説する注意点と回避法

篠山範明氏(Senior Support Engineer,Epic Games Japan)
 去る2016年8月25日,CEDEC 2016で行われた「Unreal Engine 4のレンダリングフロー総おさらい」と題するセッションは,ゲームエンジン「Unreal Engine 4」(以下,UE4)のグラフィックスレンダリングに関して,テクニカルアーティストが知っておくと役立ちそうなテクニックを解説する講演であった。
 講演を担当したのは,Epic Games JapanのSenior Support Engineerの篠山範明氏。非常にボリュームがあり,密度も濃い内容だったので,概要のレポートだけでもかなりの長編になってしまったが,興味のある人はお付き合いいただきたい。本稿でも講演の半分程度しか触れていないので,詳しく知りたい人は,インターネット上で公開されたスライドの全文を参照することをお勧めする。

SlideShareで公開中の「Unreal Engine 4のレンダリングフロー総おさらい」



G-Buffer書き出しフェーズの「Base Pass」における注意点


 篠山氏によるセッションは,冒頭でUE4のレンダリングパイプライン全体のフローチャートを示したうえで,フローチャート上の各機能ブロックに関係したテクニックを紹介するという流れで行われた。

こんな完成映像があったとき
Unreal Engine

レンダリングパイプラインの各ブロックではこんな処理が行われている
Unreal Engine

 篠山氏がまず説明したのは,フローチャートの先頭……ではなく2番めにある「Base Pass」からだ。Base Passとは,「G-Buffer」(中間バッファ)の生成に相当する。

Base PassではG-Buffer生成を行う
Unreal Engine
 UE4のグラフィックスエンジンが,ディファードレンダリング(Deferred Rendering)を採用していることを知っている人は多いだろう。Deferred Renderingとは,あるシーンのジオメトリ(3Dモデル,ポリゴン)を,ライティングやシェーディング,テクスチャの適用といったものは後回し(Deferred)にしてとりあえず描画を行い,後段でライティングやシェーディング,テクスチャの適用を行うという処理系だ。
 いわば,素のポリゴンを先行して描画するようなイメージだが,実際にはポリゴンだけではなく,ライティングやシェーディングに必要な中間パラメータも合わせて出力している。この出力先は,複数のバッファになるのが一般的だが,これらのバッファをG-Bufferと呼ぶ。

 なぜそんな面倒なことをするかといえば,Deferred Renderingには2つの利点があるからだ。1つめは,とても複雑なライティングやシェーディングを1ピクセルにつき1回行うだけですむこと。2つめは,ライティングに用いる動的な光源数に明確な制限がないため,リッチなライティングが行えるということである。
 複雑なシーンを描画するときにたくさんの光源を使って複雑なシェーダを動かす現代的なゲームグラフィックスの場合,最終的には画面に出力することなく,上書きされたり破棄されたりするピクセルをピクセルシェーダで処理することは大きな無駄で,性能を落とす原因になる。これを極力避けようとして開発されたのが,Deferred Renderingという方式なのである。

G-Bufferを可視化するとこんな感じになる,というサンプル
Unreal Engine

 ここまでを踏まえたうえで篠山氏は,このG-Bufferを出力するBase Passで注意すべき点を2つ挙げた。
 1つは,「視界に入ってこないオブジェクトは,描画対象にしない」というシンプルなものだ。
 この「視界外カリング」(Frustum Culling)という処理は,一般的にはCPU側で行うもので,オブジェクトが視界内にあるのか外にあるのかの判定は,「バウンス」(Bounding sphere)と呼ばれる各3Dオブジェクト全体を覆うようにあらかじめ設定した球状境界に対して行われる。

視界外カリングのイメージ。黄色い丸がバウンス(球状境界)のイメージ
Unreal Engine

 ところが篠山氏によれば,このバウンスが誤って(あるいは適当に)設定されているケースがあるという。その場合は正しいカリングが行われないので,最終的には描画されないのに,GPUの描画対象としてレンダリングパイプラインに投入されてしまい,無駄なGPU負荷となってしまう。

バウンス設定を正確に行わないと,余計なGPU負荷を生む原因になる
Unreal Engine

 どのくらいカリングに成功したかは,Stat InitViewsコマンドの「Frustum Culled Primitives」欄で確認可能だ。
 また,FreezeRenderingコマンドを実行してからカメラを動かすと,視界外に何が描画されているかを確認できる。もし,その時点で視界外となる部分にカリングすべき3Dオブジェクトが描画されていたら,それは何らかの理由でカリングできていないことを示しているわけだ。その場合,注意深くバウンス設定などを確認する必要があると,篠山氏は説明していた。

どのくらいカリングに成功したかは,Stat InitViewsコマンドのFrustum Culled Primitivesに表示される
Unreal Engine

FreezeRenderingコマンドを活用すると,視界外カリングが正しく行われているかを確認できる
Unreal Engine

 Base Passにおける2つめの注意点は,「無駄なピクセルを計算させない」だ。
 グラフィックス処理の流れでは,ピクセルシェーダで実際に処理を行う前の段階で,深度テスト(Zテスト)を行う「Pre Zテスト」というものがある。これから処理に取りかかろうとしているピクセルが,何かに遮蔽されるといった理由で描画されないことが明らかな場合,これを破棄するという処理だ。

Pre Zテストは,ピクセルシェーダに処理させる前にピクセルを破棄する仕組み。無駄なピクセルシェーダの実行を回避できる
Unreal Engine

 しかし,半透明オブジェクトのようにαテストをともなう描画だったり,視差遮蔽マッピングのようなピクセルシェーダ処理後に深度値が書き換わったりするような場合,そのオブジェクトはPre Zテストが行われず,処理からバイパスされてしまう。

αテストをともなうオブジェクトは,Pre Zテストが行われない
Unreal Engine

「Masked」マテリアル設定がされたものも,Pre Zテストが行われない
Unreal Engine

バンプマッピングの進化系である視差遮蔽マッピングを適用する3Dオブジェクトは,深度操作をともなうのでPre Zテストは行わない
Unreal Engine

 しかし,不透明オブジェクトでも,Pre Zテストを回避してしまうよう設定してしまうと,Pre Zテストで破棄できるはずなのに破棄されなくなってしまう。この場合,「ピクセルシェーダで処理されるが,(そのあとの)Zテストに失敗して破棄される」ので,描画結果はおかしくならないものの,性能面ではワーストケースに落ち込むと篠山氏は指摘する。

半透明オブジェクトでもないのに,Pre Zテストをパスする設定をしてはいけない
Unreal Engine

深度操作をするわけでもないのに,操作する設定にしていると,Pre Zテストが行われなくなってしまう
Unreal Engine


Z値の先だしフェーズ「Z PrePass」での注意点


 次のテーマは,「Z PrePass」である。UE4のレンダリングパイプラインでは,Base PassでのG-Buffer書き出しの前に,深度値(Z値)だけを先出しする処理として,Z PrePassを行うのだ。

Z PrePassとは,深度値の先だし工程である
Unreal Engine

 事前に深度値を先出しする目的は,最終的な映像と同じ深度バッファの内容結果を,レンダリング前に得ることにある。Z PrePassに続くBase Passでは,この先出しした深度値バッファを参照してPre Zテストを行えるので,最終的に画面には残らないピクセル(≒上書きされて消えてしまうピクセル)に対するピクセルシェーダの実行を避けられるという理屈だ。
 UE4では,背景オブジェクトのように静的なオブジェクトだけをZ PrePassに含めて,動的なキャラクターなどはZ PrePassに含めないのが,デフォルト設定となっている。しかしUE4の場合,プロジェクトファイルの「Early Z-pass」および「Movables in early Z-pass」という設定で,これをカスタマイズできるのだ。

Z PrePassに参加させるかどうかを指定する設定
Unreal Engine

 あるいは,「Use as Occluder」設定にチェックを入れることで,各オブジェクト単位でZ PrePassに含めるか含めないかを設定することも可能である。

オブジェクトごとにZ PrePassを行う,行わない設定したい場合は,「Use as Occluder」にチェックを入れる
Unreal Engine

 篠山氏は,「通常はデフォルト設定のままでいいはずだが,ポリゴン数の多いシーンでは,Z PrePassの実行自体がGPUに対して高負荷になってくる場合もあるため,そうしたシーンでは,前出の2つの設定をオン/オフしたうえで性能比較をするとよいかもしれない」と述べていた。


ライティングの前段処理系「Pre-Lighting」での注意点


 UE4では,血しぶきや弾痕といった投射テクスチャマッピングで行うデカール描画は,ライティング(Lighting)の前,すなわち「Pre-Lighting」の部分で処理する設計になっている。これは,後段のライティング処理によって,デカールがライティング対象に含まれる可能性があるためだ。
 デカールと同様に,「全方位から差し込む仮想的な環境光に対する遮蔽率」(Ambient Occlusion,アンビエントオクルージョン)の処理も,Pre-Lightingで行う。

Pre-Lightingでは,デカールやアンビエントオクルージョンの描画が行われる
Unreal Engine

 篠山氏によれば,このPre-Lighting描画に関連するトラブルでは,「デカールが焼き込みのライトマップで上書きされてしまう」とか,「スカイライトを配置するとデカールの下が透けて見える」というのが定番となっているようだ。

石畳に原色系のデカールを貼り付けたところ。縦壁からの影でデカールが消失してしまっている
Unreal Engine

六角形のマットの上に白単色デカールを貼り付けたのが左側の画像。これに天球光(スカイライト)を設置すると,なぜか六角形マットの模様が透けてくる
Unreal Engine

 結論から言えば,これは「UE4の仕様」ということなのだが,もちろん回避する策も提供されている。それが「DBuffer Decals」という機能だ。

デカールが正常に描画されない問題は,DBuffer Decalsを利用すれば回避できる
Unreal Engine

問題を解決した状態。影の部分もデカールが正常に表示されている
Unreal Engine

 DBuffer DecalsまたはDeferred Decalとは,デカールをG-Bufferとは別の,「D-Buffer」と呼ばれるデカール専用特殊バッファに描画しておき,G-Bufferを用いてのライティングやシェーディングは,D-Bufferの内容も反映しながら行うという流れになる。デカールの描画結果がG-Bufferに統合されてしまうと,これが原因で前出のような問題が出てしまう。これを回避するために専用バッファを用意したというわけだ。

 ただ,D-Bufferの利用に加えて,描画系も今までより処理のパスが増えるため,描画負荷が高くなるのがネックといったところ。
 負荷は高くなるが正確なデカール表現が行えるDBuffer Decalsを導入すべきなのか。あるいは別の表現を選んでDBuffer Decalを避けるかは,よく検討して決めたほうがいいようだ。


光源周りの扱いで性能が変わる「Lighting」フェーズ


 次に篠山氏が説明したのは,ライティングの段階である。UE4のライティングでは,「Static」「Stationary」「Movable」という3種類のライティングカテゴリが用意されている。

UE4のライティングモデルは「Static」「Stationary」「Movable」の3種類
Unreal Engine

 最初のStaticは,すべて事前計算したライトマップ的な処理で行う静的なライティングだ。この事前計算には,間接光まで配慮したライティングを計算できる専用レイトレーサー「Lightmass」を使って制作できる。

 2つめのStationaryは,光源からのライティング自体は実行時にリアルタイムで行うが,影の計算だけは事前に処理しておく方式だ。もう少し具体的にいうと,Stationary光源とは,UE4のグラフィックスエンジン内部では普通の動的光源と同等の扱いをされるが,シーンに配置されると基本的には動かない光源のこと。動かないので,影生成用のシャドウマップ生成も事前計算で扱える。

 ただ,ちょっと複雑なのだが,この仕組みが性能面でメリットとなるのは,,配置したStationary光源が1グループあたり4つまでという,内部処理的な制限があることだ。
 Stationaryでは,事前生成するシャドウマップ(テクスチャ)が,1光源あたり,αRGBの4チャネルピクセルフォーマットのそれぞれに割り当てられてられる。つまり,1つめの光源はシャドウマップのαチャネル,2つめの光源はRチャネルにといった具合だ。αRGBだと4チャネルまでしか対応できないため,1グループあたり4つまでに制限されると,篠山氏は説明していた。

 では,5つめの動的光源を設定したStationaryは,どうなるかというと,完全な動的ライティングであるMovableとして扱われるため,Stationaryとして定義しても性能向上にはならないという。

Stationary光源は,1枚のシャドウマップに4光源分まで。5つめ以降はMovable光源として扱われる
Unreal Engine

 そして,最後のMovableは,先述したように影生成も含めて,完全にすべて実行時に処理する動的光源である。

 さて,Base Passの説明でDeferred Renderingは,動的な光源数に制限がないと述べたが,実際の性能面ではどうなのだろうか。
 篠山氏は,「照射影響範囲が狭い動的光源を100個置いたシーンと,照射範囲の大きい動的光源を8個置いたシーンで,どちらが負荷が高いでしょうか?」というクイズを出題する。

左と右,どっちが高負荷か?
Unreal Engine

 答えは,後者(スライドの右)のほうが高負荷であるという。
 ここで言う負荷が高いとは,計算量が多いともいえる。そして計算量の大小は,シーン内の各ピクセルが,何個の光源による照射に影響されるかで決まってくるものだ。そのため,1ピクセルが1光源から照射されるものが8つあるよりも,1ピクセルが8光源から照射されるほうが,処理負荷は高いのである。

設置した光源の負荷率は,Light Complexityで確認できる
Unreal Engine
 UE4では,設置した光源がどの程度の負荷になるのかを確認する「Light Complexity」という機能がある。Deferred Renderingの特徴に甘えすぎず,きちんと光源の負荷を計算してシーンを設計しようというのが,篠山氏が伝えたかったことのようだ。

Light Complexityによる負荷の計算例。青が低負荷の光源で,青→緑→赤という順で高負荷となる
Unreal Engine


映り込みや鏡面反射を司る「Reflection」に正解はあるのか?


 UE4に限ったことではないが,リアルタイムのゲームグラフィックスで,何かと取り扱いにコツがいるのが「Reflection」だ。
 金属のような鏡面反射の強い材質であれば,その周囲の情景が映り込む。こうした映り込みは,素材側から見れば,全方位から照射してくる全周光源のようなものだ。Reflectionは,いわばこの全周光源に相当するもので,素材の材質を表現するときの説得力に大きく関わる重要な要素といえよう。

 さてUE4の場合,鏡像や映り込み情景のような素材,Reflectionの生成手法/取扱手法は,3種類が用意されている。

UE4における3種類のReflection
Unreal Engine

 1つは,事前生成で作る完全に「静的なReflection」だ。
 事前生成を行うポイントは,シーンにおける任意の座標位置に設定可能で,そこから全方位のレンダリングを行い,結果はキューブマップといったテクスチャとして生成される。ちなみに,全方位情景の事前生成ポイントは「Reflection Probe」と呼ばれる。

「静的なReflection」は,設定したその事前生成ポイントで撮影した360度写真のようなものである
Unreal Engine

 篠山氏によれば,問題となるのは,「Reflection Probeで取得したこの全方位情景を,シーン内のどの範囲に影響させるかという部分」であるという。
 氏は,先述した動的光源の負荷と同じような例を挙げて説明する。1シーンに1個の静的Reflectionを配置して,これがシーン内のすべてに影響するように設定した場合と,200個を配置して,それぞれがごく狭い範囲に影響するよう設定した場合とでは,描画負荷は大差がないというのだ。

広範囲に影響する1個のReflectionと,狭い範囲にしか影響しない200個のReflectionを比較すると,負荷はほぼ同程度
Unreal Engine

 しかし,200個設置のケースで,それぞれの影響範囲を大きく取った場合は,途端に負荷が増大する。
 理由は動的光源の負荷と同じだ。数の多い静的Reflectionの影響範囲を広くしてしまうと,1ピクセルを描画するのに多くの静的Reflectionを参照して計算しなくてならず,それによって負荷が増大してしまう。

200個の設置ケースで,それぞれのReflectionが影響する範囲を広く取ると,途端に負荷が跳ね上がる
Unreal Engine

 そもそも,Reflection Probeを隣接して設定しているのに,その影響範囲を互いにオーバーラップすることにそれほど深い意味はないと,篠山氏は説明する。Reflection Probeの配置と影響範囲の設定は,理に叶ったものにしなければ,無駄に負荷を増やすだけというわけだ。

 そこで篠山氏が紹介した設置の具体例は,いうなれば「Level of Detail」(LoD)的な意味合いを持たせるというものだ。
 3Dシーン全体を覆う大まかな静的Reflectionを1つ設定したうえで,シーンの大きなエリアごとに,影響範囲の広い静的Reflectionを設定する。それに加えて,ライティングやシェーディングに大きな影響を及ぼしそうなものがあれば,そこに局所的な静的Reflectionを設定するといった具合だ。

理に叶った静的なReflectionの配置例
Unreal Engine

 2つめのReflectionは「Screen Space Reflection」,通称SSRである。SSRは,レンダリング結果に対して,画面座標系での局所的なレイトレーシングを行い,Reflectionをランタイム上で,なおかつリアルタイムに生成するという事前計算なしの手法だ。
 シーンの一瞬を切り取っても,動的キャラクターや動的光源の影響などを正確に反映したReflectionが得られるのは利点であるが,画面外に存在する情景の影響は,一切,無視されてしまう欠点もある。
 SSRによる典型的なエラーは,この弱点が露呈したときに起こりがちだ。これを補うのに有効なのは,静的Reflectionを組み合わせることであるという。

SSRの典型的なエラーを示したスライド。画面左側の切り立った壁も水面に反射していなければならないのだが,その壁が画面外にあるため,正しく反射できていない
Unreal Engine

 3つめのReflectionは,「Planar Reflection」だ。
 これは,平面に映り込む情景を正確に描画できるReflectionの手法である。下の図版を例に説明すると,映り込み対象の面(たとえば水面)に対して,水面に潜った位置に視点(E’)を置き,上下を逆転してシーンをレンダリングするようなものだ。そのシーンを2回描画しているような処理を行うため,必然的にかなり高負荷なReflection処理となる。

Planar Reflectionの概念図。「視点E」が描画起点で,「法線N」は映り込み対称面の向き。この映り込み対称面に対して,線対称となる「視点E'」から上下を逆転させて描画した情景が,映り込み対称面に映り込む情景となる。拙著「ゲーム制作者になるための3Dグラフィックス技術」(Amazonアソシエイト)より引用
Unreal Engine

処理負荷が高いため,Planar Reflectionは水面や廊下といった平面への映り込みに用途が限定されるものの,映像品質は高いとのこと
Unreal Engine

 篠山氏は,このPlanar Reflectionについて,「カットシーンなど,クオリティが必要な場面での活用を推奨する」と述べていた。実際,GDC 2016で公開された「Hellblade: Senua's Sacrifice」(PC / PS4)のカットシーンにおける水面への映り込みは,Planar Reflectionを使って生成されているそうだ。



半透明にまつわるエトセトラ


 UE4に限った話ではないが,半透明オブジェクトの描画は,リアルタイムグラフィックスにおいては厄介なテーマである。「UE4でも,半透明オブジェクト描画に関連した厄介ごとは少なくない」と,篠山氏は正直に述べていた。
 とくに身近で厄介な半透明オブジェクトは,パーティクルエフェクトである。ゲームグラフィックスに携わる日本のアーティストは,パーティクルエフェクトが大好物なので,この問題への関心は高いのではないだろうか。

 UE4の場合,半透明パーティクルの描画時には,深度値(Depth)の更新を行わないという。

UE4では,半透明エフェクトを描画しても深度値は更新しない
Unreal Engine Unreal Engine

 この場合に起こりうる問題といえば,深度値をキーにして行うポストプロセスがおかしくなるというものだ。
 下に掲載したスライドは,数m先の炎にフォーカスが合っていて,それより奥は被写界深度表現でボケ味を与えたという画像だが,描かれた炎のパーティクルが,地平線を境界線にして上側だけがボケて,地平線の下側はボケていないという変な描画になってしまっている。

半透明エフェクトに被写界深度表現のポストプロセスをかけてみると,地平線より上だけがボケてしまうというおかしな映像に
Unreal Engine

 これは,炎パーティクルに対応する深度値がなく,地面の描画に対応する深度値しか深度バッファ(Zバッファ)に存在しないことが原因だ。地平線から上の背景は非常に遠いので,背景も炎もまとめて焦点から大きくはずれていると判定されて,同じ被写界深度でボカされるという理屈である。ボケフィルター側からすれば,炎パーティクルが描かれているかどうか知りようがないので,結果的にこんな有様になっているのだ。

 篠山氏は,こうした描画不具合に対する解決策として「Separate Translucency」を紹介した。
 Separate Translucencyでは,半透明パーティクル描画時に深度値の更新を行わないことは変わらないものの,被写界深度表現のようなポストプロセス処理から切り離された別のバッファに,半透明オブジェクトを描画できるという。
 いわば,半透明オブジェクトと不透明オブジェクトとの描画を分離(Separate)させて,ポストプロセスは不透明オブジェクトの描画先だけに適用するような処理系とするわけだ。

通常のレンダリングプロセスでは,パーティクルの描画先と普通のシーンの描画先は同じバッファであった
Unreal Engine

Separate Translucencyを使ったレンダリングプロセスでは,パーティクルの描画先を別バッファに分離することで,ポストプロセス(この例ではボカし)対象から分離させる
Unreal Engine

左が今までの描画で,右が半透明オブジェクトの描画を切り分けた描画の例
Unreal Engine

 このテクニックを使うと,半透明パーティクルに対する変なボケの適用は回避できるのだが,半透明パーティクルに対して適切なボケを与えられない。問題の回避はできても,適切な処理は行えていないのである。
 この点について篠山氏は,現在のUE4における仕様制限のひとつであると述べていた。現在,UE4のエンジニアやベテランユーザーの間で,うまい解決策がないか議論中だとのことなので,それが見出されることに期待しよう。

半透明オブジェクトとポストプロセスの組み合わせにおいては,今のところ後ろ向きなエラー回避策しか用意されていない
Unreal Engine
Unreal Engine

 さて,半透明描画にまつわる厄介ごとには,もうひとつ定番の問題がある。それは描画負荷が高くなりがちという問題だ。
 ここでも篠山氏はクイズを出題した。「画面全体の色を変更するポストエフェクトと,画面の一部に立ち上る煙のパーティクルエフェクトのどちらが高負荷でしょう」というものだ。

左は画面全体の色を変える処理で,右は画面の一部に半透明パーティクルの煙を描画している処理。どちらが重い?
Unreal Engine

 単純に考えれば,画面全体のほうが処理するピクセル数が多そうに思えるが,答えは右だ。
 一見すると,半透明パーティクルの煙は画面の一部にしか描かれていないように見えるが,実は何度も重ね描きされている。それは,パーティクルをワイヤーフレーム表示した画面を見ると一目瞭然だ。画面内の同一領域に,煙パーティクルが大きさを変えて,何度も重ね描きされている。

煙のパーティクルをワイヤーフレームで表示させると,多数のパーティクルを重ね合わせることで描画していることが見て取れる
Unreal Engine

 篠山氏は,この半透明パーティクルの重なり具合を視覚化するテクニックとして,「Shader Complexity」のデバッグビューを紹介した。
 このデバッグビューは,ヘビーに反復描画されている領域を赤く表示して可視化することで,問題が生じている部分を判断できるというもの。赤い部分があれば,パーティクル描画の負荷を低減すべきであるというわけだ。

Shader Complexityのサンプル画面。パーティクルの重なりを赤く表示している
Unreal Engine

 パーティクル描画の負荷低減策として最も効果的でシンプルなテクニックとして,篠山氏は,別バッファに分離してパーティクル描画を行わせるSeparate Translucencyを,低解像度で描画するというやり方を説明した。
 反復描画によって,重ね描きする半透明パーティクルを低解像度で描画したうえで,メインのレンダリング結果と合成するときに,適当なサイズに拡大して合成するわけだ。半透明パーティクルの描画先バッファを縦横半分の解像度にすれば,単純計算で描画負荷は4分の1にできる。その半分ならば16分の1で済む。

半透明オブジェクトの描画を低解像度で行う「r.SeparateTranslucencyScreenPercentage」コマンドを利用する
Unreal Engine

 低解像度バッファに描画し,それを拡大してから合成するということは,パーティクルの輪郭が強くボケるわけだが,もともと半透明パーティクルはもやっとしたものなので,影響は少ないだろうというのが篠山氏の考えである。あまり解像度を下げすぎると,解像度の不一致が露呈するので,バッファの描画解像度は慎重に選ぶ必要があるものの,処理負荷軽減効果は大きいとのことだ。

上から順に,半透明オブジェクトのバッファ解像度を100%,50%,10%で描画した状態。描画負荷は50%時で3割,10%時では5割以上低減できたとのこと。ただし,不透明バッファと半透明バッファを合成した結果の画像を見ると,解像度が一致していないことが露呈することもある。画像左側にある階段状のジャギーがまさにそれ
Unreal Engine
Unreal Engine
Unreal Engine

 篠山氏は,パーティクル描画の負荷低減策として,もう1つのテクニックを提示した。それは,パーティクルアニメーションなどで,半透明領域ではなく完全透明領域が多い場合に利用できる「Particle CutOut」だ。

 通常のパーティクルは,2枚のポリゴン(三角形,または四辺形)で構成されるわけだが,完全に透明な領域を避けるように,複数のポリゴンに自動分割して描画するというのが,Particle CutOutの考え方となる。
 ポリゴン数は増えることになるが,無意味なピクセルシェーダに実行を避ける効果が期待できるため,大量のパーティクル描画を行う状況では,負荷低減に結びつけられるかもしれないという理屈だ。

左が2枚のポリゴンからなる四辺形のパーティクル。右が完全に透明な領域を避けて,5枚のポリゴンによる多角形で構成したパーティクルだ
Unreal Engine

Shader Complexityのデバッグビューで見た状態。左が四辺形パーティクル,右が多角形パーティクルによる描画を観測したもので,右のほうが重複描画(赤い領域)領域を小さくできているのが分かる
Unreal Engine


処理順序が固定されているUE4のポストプロセス


 描画結果に対して,最後にフォトレタッチをするような感覚で加工を行うのがポストプロセスだ。
 フォトレタッチは通常,2Dの写真に対して行うものだが,3Dのゲームグラフィックスにおいては,レンダリング結果に付随するさまざまな情報を用いて,3次元の加工を施すことができることが大きな違いである。

ポストプロセスなし(左)とあり(右)の比較スライド
Unreal Engine

 UE4は,色変調や被写界深度表現,ブルームなど,画像をフォトリアルな見た目に加工するための,さまざまなポストプロセスエフェクトを備えている。

UE4が備えるポストプロセスエフェクトの例
Unreal Engine

 UE4で特徴的なのは,ポストプロセスの効果を3Dシーン内の特定位置,またはカメラに設定できるところだ。たとえば,「3Dシーンのとある場所に入ってきたら被写界深度表現がかかる」とか,「このカメラで描画したときにはセピア調になる」といった処理が実現できるのである。

ポストプロセスの効果は,特定の場所にセットしたり,特定のカメラにだけかけたりできる。
Unreal Engine

ポストプロセスの効果に重さを付けたり,優先度の設定も設定可能だ
Unreal Engine

 篠山氏は,UE4特有のポストプロセスの処理順序については,事前に覚えておくといいとアドバイスしていた。この処理順序は変更できず,必ずこの流れで実行されるためだ。
 たとえば,「モーションブラーを先に行ってから被写界深度表現を行う」ことはできない。もし,設定したパラメータに対して,想像と違う結果になった場合は,この処理順序に依存した問題である可能性を疑ったほうがいいかもしれない。

UE4におけるポストプロセスの処理順序は変更できない
Unreal Engine

 余談気味だが,篠山氏は,UE4のツール上では公開されていない,コマンドラインによるポストプロセスのパラメータ設定手法があることにも言及している。
 セッションではその一例として「r.BloomQuality」という,ブルーム効果の広がりを設定できるパラメータを紹介した。

ブルーム効果の広がりを設定できる隠しコマンド「r.BloomQuality」が紹介された
Unreal Engine

 こうした隠しコマンド的なコマンドパラメータは,どのように見つければいいのか。以前であれば,UE4のソースコードを開いて,そのコメント欄を探すしかないという,正真正銘の隠しコマンドだった。しかしCEDEC 2016時点で最新版となるUE 4.13には,コマンドラインによるパラメータのヘルプをHTMLファイルに出力する「Console Variables」という仕組みが実装されたという。

コマンドラインパラメータのヘルプを出力する仕組み「Console Variables」が,UE 4.13に実装された
Unreal Engine

出力されたHTMLファイルを閲覧すると,こんな具合に隠しコマンドを確認できる
Unreal Engine

 すべて英語表記ではあるが,これらの隠しコマンドによるパラメータを駆使することで,より深いポストプロセスのコントロールを行ったり,処理の順序依存を克服するような設定を行えるかもしれないと,篠山氏は述べていた。


UE4を使うアーティストにとって実用的なセッション


 UE4は,プログラミングにそれほど明るくないアーティストであっても,容易にゲーム開発ができるゲームエンジンといわれる。ただ,リッチなグラフィックス表現を追い求めれば,いくらでも凝ることができるため,「せっかく作り込んだはいいが,いつのまにか性能が出ない……」という状況になってしまうことも少なくないようだ。
 そんなときに役立つのが,グラフィックスエンジンの処理系に対する理解である。処理系に対する知識が多少なりともあれば,重くなりにくい表現の制作も可能になるだろうし,性能を犠牲にしなくても高いレベルの表現にも挑戦できるようになるかもしれない。その意味では,篠山氏による今回のセッションは,かなり有用だったのではないだろうか。

 実際,セッション後に筆者が聴講者に軽くヒアリングしてみたところ,UE4を使ってゲーム開発に携わる人がつまずく代表的な課題が一通り網羅されていて,とても有用なセッションだったという声が聞かれた。ぜひセッションの内容を生かして,よりよいゲーム作りに取り組んでいただきたい。

SlideShareで公開中の「Unreal Engine 4のレンダリングフロー総おさらい」

CEDEC 2016 公式Webサイト

4GamerのCEDEC 2016関連記事一覧


  • 関連タイトル:

    Unreal Engine

  • 関連タイトル:

    ミドルウェア/開発ツール

  • この記事のURL:
line
4Gamer.net最新情報
最新記事一覧へ新着記事10件
トピックス
スペシャルコンテンツ
注目記事ランキング
集計:05月25日〜05月26日