背景も含めたすべてをトゥーンで描く『Hi-Fi RUSH』
本セッションは『 Hi-Fi RUSH 』のゲーム紹介とグラフィックスに求められたスペックの紹介から始まり、田中氏による描画パイプラインの解説、駒田氏によるNiagaraによるGPU物理シミュレーションの解説 が続きました。
キャラクターはトゥーンでも 背景はPBR (Physically Based Rendering)で表現されるタイトルが多い中、『Hi-Fi RUSH』はキャラクター、背景、VFXなど、ゲームの中で描かれる 世界のすべてが独自のトゥーン表現で描画 されています。加えて、カットアウト(色数の削減)、Halftone、斜線ハッチングによるスタイライズ表現が特徴です。
『Hi-Fi RUSH』は リズム アクション ゲーム であるため、入力遅延の小ささが求められます。それゆえ、グラフィックスでの遅延は許されません 。
ディレクターからは「絵のクオリティよりも60FPSを優先する」と開発初期から言われてきたとのこと
そこで、開発ターゲットであるXbox Series S、Xbox Series Xの想定解像度で60FPSが出せることが、本作のトゥーン表現の目標に設定されました。
※ なお、本作はWindowsでもプレイ可能
目標解像度はXbox Series SでWQHD(1440P)、Xbox Series Xで4K。最終的には、Steam Deckでも60FPSが出るパフォーマンスが実現できた
本作はUnreal Engine 4(以下、UE4)で開発されており、最終バージョンは4.27.2。60FPSを保ちつつ世界全体をトゥーンで表現する目標を実現するため、本作がどのように Deferred Toon Rendering を実装したのか、見ていきましょう。
描画パス追加に伴う描画パイプラインの設計方針
『Hi-Fi RUSH』ではエンジン改造を施し、UE4標準のディファードレンダリングの描画パイプラインを、以下のように拡張しています。
描画パスを追加し、独自のDeferred Toon Renderingを実装
UE4標準ディファードレンダリングのよい箇所はスタイライズして利用
UE4の処理負荷が重い箇所は自前で描画パスを追加して代替機能を実装
本作独自の描画機能。黄色い部分はUE4既存機能を独自にカスタマイズして実装した
なお、エンジン改造にあたってはマージ問題やプラグインの互換性を考慮して、以下の方針をとったとのこと。
既存ソースコードの変更は最小限に
なるべく新規ソースコードに新規パスを追加する
必須ではない改造は行わない
Base Passまで: G-Bufferを増やさず用途変更で負荷軽減
本セッションでは、下記画像のシーンを例に描画パイプラインの説明が行われました。
上図のシーンでDeferred Toon Rendering用に生成される描画バッファ
Depth Prepass Depth Prepassでは、シーン全体の 深度バッファ (Depth Buffer)を生成します。
なお、Depth Prepassは、DBuffer Decalを有効化することで実行されるUE4標準のパスです。
Deferred処理では、複数の描画パスでワールド座標の計算に深度バッファが用いられる
Shadow Pass UE4標準の影描写パスです。Dynamic Shadowを有効にしたライトごとに Shadow Depth Texture を生成しています。
本作では、後述する 影OnlyLight のSpotLightによるDynamic Shadowや平行光源の Cascade Shadow Map がここで描画されます。
パフォーマンスを考慮すると、Dynamic Shadowの使用は最小限に抑えるべきです。本作では、SpotLightのDynamic Shadowは専用の「影OnlyLight」でのみ使用できるようにしています。影OnlyLightを設置する「影LightActor」は、処理負荷に余裕があり、配置が効果的なシーンでのみ使用が許可されます。
影OnlyLight以外のSpotLightでは、Dynamic Shadowを無効にしている
影OnlyLightはShadowをCastする対象を制限できる。例えばプレイヤー用影OnlyLightでは、プレイヤーキャラクターであるチャイのみの影をShadow Passで描画する
最終描画結果では、プレイヤーであるチャイの影(中央)は斜線ハッチング表現でスタイライズされる。背景から落ちている影(左)は、Dynamic Shadowではなく後述するStatic Shadow Mapによるもの
Base Pass モーションブラーやTAA( Temporal Anti-Aliasing)で使用されるVelocity BufferがVelocity Passで作成された後、 Base Pass が描画されます。ほとんどのマテリアルは、このBase Passで描画されます。UE4のディファードレンダラーにおけるGeometry Passに相当する、重要なパスです。
本作のBase Passは、主に 「Deferred Toon Renderer用の G-Buffer 作成」と「Forward Lighting処理のToonの Lit/Shade決定 と Forward Light によるライティングを行う」という2つの役割を持っています。
Base Pass - G-Bufferの用途変更 『Hi-Fi RUSH』のG-Bufferは、RGBA8 ×3枚(G-BufferA、B、C)の標準的な構成です。処理負荷の増加を考え、Deferred Toon Renderer用の追記情報についてはBufferを増やすのではなくG-Bufferのチャンネル用途を変更することで対応しています。
本作のトゥーン表現ではMetallicとSpecular、G-BufferAO情報は不要だったため、その中でも修正箇所が少ないであろうSpecular、G-BufferAOをDeferred Toon Renderer用追記情報の格納に使用した
追記情報を格納する手段としては、UE4の「Custom Stencil 」機能も選択肢となりますが、この機能を使用したオブジェクトには新たにCustom Stencil用の描画パスが追加されるため、処理負荷が増加します。
本作ではCustom Stencilを、回復アイテムを取得したときのハイライト処理など、オブジェクト単位に設定するものや使用頻度が低いものに使用した
そこで、本作では前述した不要なG-Bufferのチャンネルを、Stencil Bitとして扱うよう改造しています。この「G-Buffer Stencil」と呼称される機能により、Stencil機能をMaterial単位でかつ処理負荷を気にせず使えるようになりました。
G-BufferAOのG-Buffer Stencil Bitフラグ。キャラクター判別やPost Process Outlineの処理スキップに使用
SpecularのG-Buffer Stencil Bitフラグ。平行光源や影OnlyLight、各種ライティング効果の適用Skipに使用
なお、G-Buffer StencilはG-Bufferを持たないUnlit やTranslucent マテリアルには使用できませんが、これらのマテリアルはそもそもDeferred Toon RendererによるToon処理を行わないため問題にはならなかったそうです。
Base Pass - Forward Lighting メインのLighting処理はDeferred Passで行われますが、 Forward Lighting はBase Passの段階で 計算されます。Forward Lightingを導入したのは、Base Passでの処理ゆえエンジン改造が不要であり、ライティングの試行錯誤がしやすかったからだそうです。
Toon処理における Lit/Shade 状態はBase Passで計算します。Lit ColorはG-BufferCの Base Color に格納しています。 Shadow Color は IsShadeMaskフラグ をG-Buffer Stencilに格納し、実際のShadow Colorはフラグを用いてDeferredで後続のPassで決定しています。
上記画像は室内のシーンなので全面でIsShadeMaskフラグが立っており、Shadow Colorで描画されている
上記画像のシーンではForward LightingのCutout機能を使用している。専用Forward Lighting Actorを配置してシーンをライティングしている
Forward Lightingの計算結果によりマイナスライトになった場合、後続のDeferred処理が暗くなりすぎる問題が発生したが、G-Buffer StencilにIsForwardLitビットを追加し後のパスで調整している
Base Pass までが完了し、ここまでで深度バッファ、Shadow Depth Texture、G-Bufferが生成されています。
左上が深度バッファ、左下がShadow Depth Texture。上段右から3つがG-Buffer×3
Lighting Passまで: Volumetric LightmapをActor単位でベイクするように
Ambient Occlusion Pass Base PassのあとにはUE4標準のSSAOで Ambient Occlusion を描画するパスが続きます。
SSAOの描画結果。光り具合などの調節はPostProcess Volumeなどで行っている。この段階ではキャラクターやEmissiveにもSSAOが描画されている
最終描画段階では、G-Buffer Stencilを利用してキャラクターやEmissiveにはSSAOがのらないようにしている。また、後述するパスによりSSAOに斜線ハッチングのスタイライズ表現が適用される
上記画像の拡大部分にも斜線ハッチングが使用されている。距離によるフェードを導入することで主張しすぎないよう調節した
Capsule Shadow Pass Capsule Shadow もUE4標準のものを使用しています。
前述の通り、Dynamic Shadowは処理負荷の高さから使用を制限しています。本作では処理負荷の低いCapsule Shadowを使用することで、シーンのライティングに関わらず常にNPC、Partner、敵キャラクターの影を落としています。
Capsule Shadowの描画結果。UE4標準ではSSAOと同じRender Targetで描画されるが、本作ではエンジン改造により独自のRender Targetで描画される
Capsule Shadowにも斜線ハッチングをかけている
World Volume Lighting Pass World Volume Lighting Pass は、UE4の Volumetric Lightmap を改造したProbeベースのGlobal Illumination(GI)パスです。
UE4標準のVolumetric Lightmapではレベル単位でベイクされますが、 World Volume Lighting Pass ではActor単位です。
画像中央にあるデータスフィアを囲むようにWorld Volume Lighting Volumeが配 置され、Volume内の空間限定でVolumetric Lightmapがベイクされている
これにより、ベイクにかかる時間を短縮できるほか、球面調和関数によるAmbient情報のみを保存するように改造したためデータも軽量化。また、描画範囲をVolumeの空間内に制限できるため、描画処理が高速化します。
可視化したProbe(画像中の黒いSphere)。配置された複数のWorld Volume Lighting VolumeそれぞれでProbeが生成されている
World Volume Lighting Passの描画結果。Static LightやEmissiveによるDiffuse GIが反映されているのがわかる
World Volume Lightingの最終描画結果
AO Volume Pass AO Volume Pass は今回新規で追加した描画パスです。
物体との距離が遠くCapsule Shadowの影が届かないときの丸影を描画します。主人公チャイの周りで浮いている猫型ロボット808や浮遊している敵などは地面から離れているため、このパスで影が描画されます。
AO Volume Passによる影にも斜線ハッチングをかけている
Lighting Pass UE4の標準ディファードレンダリングのShading Passにあたる Lighting Passは、エンジン改造により、独自Deferred Lightの描画と、影OnlyLightのタイプ情報を描画するPassになっています。
32-bit HDRについて見ていきましょう。本作ではパフォーマンスの都合からr.SceneColorFormatをデフォルトの64-bit HDR Scene Colorではなく32-bit HDR Scene Colorにしています。
ただし、32-bitにするとR11G11B10形式となり、Alpha Channelがなくなってしまいます。ライティングの結果に影タイプの情報を書き込むのにAlpha Channelが必要だったため、新規追加した独自描画パスで32-bit HDRのSceneColorを64-bit HDRの新たなLighting Bufferにコピーしています。
続いて影有りライトに対し、UE4標準パスのShadow Projectionパスを実行します。
今回のシーンでは、プレイヤー用の影OnlyLightのShadow Mask Textureを描画。Shadow Passで生成したShadow Depth TextureをScreen Space投影している
次のパスで実際にDeferred Lightを描画します。なお本作ではエンジン改造しているため、Deferred Lightではなく、独自のDeferred Toon Lightを描画しています。
例に挙げたシーンでは、プレイヤーの影OnlyLightがDeferred Toon Lightとして処理されている。影OnlyLightにはShading処理は行われず、Alpha ChannelへのShadowのタイプ情報の描画のみ行われる
Deferred Lighting Passの描画結果。Lighting BufferのRGB Channelにはライティングの結果が描画される
Lighting PassのAlpha Channel。Shadowのタイプ情報が書き込まれている。上記の場合、プレイヤーの足元に描画されている影がプレイヤーの影であると識別する情報が書き込まれている
下記画像がLighting Passでの生成バッファです。
左上からSSAO、Capsule Shadow、AO Volume Pass。右下からWorld Volume Lighting、Lighting PassのAlpha Channel、そしてLighting PassのRGB Channel
Toon Post Process Pass手前まで: Mip Levelの変更でRoughnessを表現
Reflection Pass Lighting Passの次は Reflection Pass です。ReflectionにはUE4標準の Screen Space Refrection (SSR)を使用しています。パフォーマンスを考慮して、SSRの品質はmedium(no glossy)設定を採用しています。
次は、本作独自の「SSR Mipmap」生成パスです。本作ではGlossy表現をMipmapのボケを使用した簡易的な表現で独自実装しています。
Reflectionの最終パスで、先ほど生成したSSR Mipmapを用いたGlossy計算とトゥーン調のスタイライズ処理を行います。
Roughness値が高いほど低解像度の(よりボケが強い)Mip Levelを参照することで、処理負荷の軽い簡易的なGlossy表現を実現しました。
Glossy計算はSSR Mipmapを参照し、アーティストが作成したRoughness – Miplevel変換テーブルを使用して行う
スタイライズでは、4段階にGlossy SSRの色情報を単純化する Posterize Cutout化 と、SSRの輝度に応じてサイズを変化させる Screen Space Halftone を施しています。
Reflection Passの処理をすべて反映したもの
Static Shadow Map Pass Static Shadow Map Passも新規追加した描画パスです。アーティストが影を利用できるよう、 静的影 をベイクできる仕組みとして用意されました。
Static Shadow Mapには2つのメリットがあると田中氏。 ひとつは、Depth Pass不要である点とVolume内に描画範囲を制限できる点による負荷の低さ。
もうひとつが、アーティストが狙った位置に狙った影を落とせる、2D的な絵作りとの相性のよさです。
Static Shadow Map Passの描画結果
上記画像では、プレイヤー以外の影はすべてStatic Shadow Mapによる静的影。アートディレクションによりStatic Shadow Mapには斜線ハッチング表現をかけないケースも多いが、上記画像の拡大部分のようにかけることもできる
Decal Light Pass Decal Light Pass も新規追加した描画パスです。
Decal Lightはシェーディング計算は行わず、狙った形状のライトをオブジェクトに投影する投影ライト として使用しています。
投影範囲を指定するDecal Light Decal Volumeを使用することで描画面積を減らすことができる。上記画像のように地面に薄くVolumeを配置すれば、Decal Lightは壁などには描画されず、地面の部分でのみ描画される
Render Target別のDecal Light Passの描画結果。こちらはDecal LightのLighting Buffer
こちらのRender Targetには、後述のDeferred Toon Rendering Shading PassでBase Colorが調整できるよう、RGBにはRGB調整色を、AlphaにはDecal Lightの最終計算結果のBlend率を入れている
Post Process Outline Pass Post Process Outline Pass も新規追加した描画パスです。トゥーンレンダラーに多用されるアウトラインを生成するためのパスです。
本作ではポストプロセスによるアウトラインはキャラクターには採用せず、背景にのみ使っています。 Depth Outline 、 Normal Outline を計算し、画面内のメッシュが占める領域の 内側 に描画しています。
一方、キャラクターのアウトラインには 背面法 を採用しています。というのも、メッシュの内側に描画するアウトラインでは、カメラを引いた時にキャラクターがアウトラインで黒つぶれしてしまうためです。
なお、キャラクターと背景はG-Buffer Stencilを利用して判別している
Post Process Outline Passでの描画結果。キャラクターには使用していないため、キャラクターのアウトラインはここでは表示されない。また、遠方の背景も描画しないように距離フェードが反映されたAlpha値も格納している
下記画像がLighting Pass後からPost Outline Passまでの生成バッファです。ここまでで、Deferred Toon Rendering用の入力バッファはすべて生成されました。
左上から、Reflection Pass、Static Shadow Map Pass、Decal Light Pass × 2、Post Process Outline Pass
Toon Post Process Pass: メインのトゥーン処理
Toon Post Process Pass は、Deferred Toon RenderingにおけるShading Passです。これまで計算してきたG-Bufferやその他の描画結果を利用して 最終的なトゥーンシェーディング処理 を行います。
Toon Post Process Passが利用する描画バッファ。Toon Post Process Pass単体のパスで最終描画まで行うことで、プレイヤーの動的影がStatic Shadow Mapの影と重なった時にどうするかなど、各要素の相互影響を考慮に入れて描画を行うことができる
Toon Post Process Pass実行前(左画像)と実行後(右画像)のScene Color
Deferred Toon Post Process Volume 通常のディファードレンダリングのShading PassではライトをライトのGeometryで描画します。
通常のディファードレンダリングでは、Point LightならSphereを描画、Spot LightならばConeを描画する
それに対し、 Deferred Toon Post Process では、Box形状の Deferred Toon Post Process Volume で囲まれたGeometryに、同Volumeで指定されたパラメーターに基づいてToon Post Processを適用します。
例えば上記画像において、Deferred Toon Post Process Volumeの中と外では、Toon Color、Ambient Color、SSAOの乗り具合が別パラメーターで描画されている
これにより、ポストプロセスのパラメーターを空間単位で調節でき、より柔軟なトゥーン表現が可能となります。
上記画像では、エリア全体を囲むVolumeのほか、中央にあるデータスフィア付近にもVolumeを重ねて配置し、場所ごとに雰囲気を調整している
Deferred Toon Post Process Volumeの 重なり は、描画済みかどうかを判別するフラグをCustom Stencilのbit0に格納し、描き込み時にフラグをチェックすることで、同じピクセルに対し複数回の描画がされないよう最適化しています。
UE4におけるCustom Stencilのbit0は、Sandbox Stencilとしてシェーダー内で自由な使い方ができる
3D TextureとAmbient Cubemap Textureを使用した空間的ライティング処理 Lit Base ColorはBase Passで決定される一方で、 Shadow Color はDeferred Toon Post Process Passで決定されます。
空間に対する色情報を格納した3Dテクスチャ を変数として持つShadow Color Volume Actorをシーンに配置することで、空間単位でShadow Colorを調整しています。
画像右にある3Dテクスチャの色がシーンに適用されている
また、6方向の Ambient Cubemap を使い、3D空間に対して大まかな陰影づくりをしています。
3Dのように見えるのを避けるため、グラデーションが目立たないように調整されたテクスチャを使用している
画像右のCubemap Textureが、メッシュのそれぞれの面に対してAmbient Lightとして適用されている
なお、Shadow Color VolumeやAmbient Cubemap Volumeの処理は負荷軽減のため独自描画パスを追加せず、このToon Post Process Passで行っています。
各描画パスのスタイライズ処理 ここまでのパスでのライティング結果がこのToon Post Process Passで最終描画結果に適用されます。まだスタイライズが行われていないパスに関しては、Litに対してはHalftone 、Shadowに対しては斜線ハッチング を適用する処理が行われます。
SSAOの斜線ハッチング(下の拡大部分)やWorld Volume LightingのHalftone(上の拡大部分)などはここで適用される
ここまでで紹介したように描画パスを拡張しつつ、それでも60FPSの目標が実現できたのは「技術の採用の段階でパフォーマンスを意識したこと」と「軽い処理負荷でトゥーン表現の3D描画処理をどう実現するかを考えたこと」が大きかった、と田中氏。あらためて拡張方針を振り返り、描画パイプラインについてのパートを締めました。
PBDを使ったNiagara製コイン飛散エフェクト
※ 以下、ゲーム終盤のシーンの紹介が入りますのでネタバレにご注意ください
ここからは、駒田氏が NiagaraによるGPU物理シミュレーション について解説しました。
本作では、床に コイン がギッシリ配置された部屋で戦闘するシーンがあり、シーン内では、キャラクターやギミックの動きに応じて飛び散るコインのエフェクトが発生します。
開発においては制作コストを考慮し、手付けではなく 物理シミュレーション でコインの飛び散りを表現しました。
VIDEO
床に配置されたコインが飛び散るシーン(ゲーム終盤のシーンのため、ネタバレにご注意ください)
コインのエフェクトには、以下の要件が求められました。
キャラクターやギミックの動きに反応して飛散すること
物量の多さを感じられること
パフォーマンスで足を引っ張らないこと
手付けのエフェクトに近い自然さと格好良さがあること
そこで、簡易な剛体シミュレーションをNiagaraで実装し、GPU上でシミュレーションを実行する方針をとりました。
物理シミュレーションのシーン設定 当該ボスと戦闘するシーンでは、シミュレーション範囲を指定するボックス形状の Volume が配置されており、その底面に64,000枚のコインパーティクルがスポーンしています。配置されたコインは、キャラクターやギミックとの衝突により飛散します。
コインは碁盤目状に配置されると飛散軌道に不自然な対称性が出てしまうため、ランダムに配置しています。
実際のVolumeの底面は コイン床のスタティックメッシュ に覆われているため、パーティクルのコインはコイン床メッシュから飛び出たときのみプレイヤーの目に触れます。動かない大量のコインで覆うことで、少ないコインを飛び散らせるだけでも見栄えがするとのこと。加えて、飛散していないコイン同士のめり込みを隠せるため、コイン同士のコリジョン判定を計算する必要がなくなります。
Volumeを実際の床から少し浮いて配置することで、コインの飛散が上方向になり見栄えがよくなる
コインは、Volumeのほか、キャラクターおよびギミックに追加した専用コライダとコリジョンします。
プレイヤーには、身体部分にカプセルコライダ、足元にスフィアコライダが設定されている
物理シミュレーションの実装 物理シミュレーションには挙動の安定性から Position Based Dynamics(PBD) が採用されています。
コインの物理シミュレーション処理は、毎フレーム実行されるParticleUpdate内の「 コライダの更新 」「 スリープ状態の更新 」「 積分 」「 コリジョンコンストレイント解決 」で構成されています。
キャラクターとギミックのコライダは移動や増減があるため、 コライダの更新 が必要です。
そこで、毎フレームVolume内にある特定のObjectTypeを持つコライダを検出し、コライダの形状、位置、向き、サイズ情報をシミュレーションに渡しています。
各コインは床の動摩擦により速度が一定値を下回ったら スリープ状態 に移行します。スリープ状態では描画およびシミュレーション処理をストップし、負荷を削減。また、コインの移動による配置ムラを防ぐため、スリープ時に初期配置位置に戻ります。スリープ状態のコインは、キャラクターやギミックのコライダが一定距離に近づいたらスリープが解除されます。
VIDEO
コインが飛び散る様子と、スリープに入りコインが初期位置に戻る様子
積分 処理では、通常のPBDと同様の処理に加え、剛体であるため向きと角速度も扱っています。
コリジョンコンストレイント解決 では、通常の剛体シミュレーションであればコリジョンをメッシュと同じ円柱形状で扱うところ、今回は計算量を減らすために ディスク形状 として扱っています。
ディスクの中で最も深くコリジョンにめり込んだ点のみを衝突点として近似している
コリジョンしたコインには、「 めり込まない位置にコインを移動させるための押し出し 」と「Volumeに当たった際の 反発力と動摩擦の適用 」の2つの処理を行っています。また、Volumeとコライダは無限質量扱いとし、コインのみが位置調整されるようにしています。
キャラクターとギミックに対しては反発と動摩擦がなくても表現としては問題がなかったとのこと
パフォーマンスを測定したところ、シミュレーションと描画をあわせた処理時間は1.0msに収まった
最後に駒田氏の経験から、GPU物理シミュレーションを実装する際は、「ステップ実行が容易なCPU側で十分な検証と実装を済ませてからGPU側に移植する」「精度の観点から、シミュレーションはワールド座標系ではなくローカル座標系で行ったほうがよい」というアドバイスがありました。
配置コインの64,000枚は「GPU物理シミュレーション」という設定項目がデフォルトの「低」になっているときの値で、これを「中」にすると128,000枚、「高」にすると256,000枚になる。「高」だと飛散枚数が多すぎてプレイヤーキャラであるチャイが見えにくくなるので難易度も上げることができる…とのことだが、駒田氏曰く残念ながらこれについて触れているレビューを見たことがないそうだ
『Hi-Fi RUSH』製品紹介ページ 『Hi-Fi RUSH』開発事例 グラフィックスと最適化紹介 | UNREAL FEST 2023 TOKYO 公式Webサイト
© 2023 Bethesda Softworks LLC, a ZeniMax Media company. HI-FI RUSH, Tango, TangoGameworks, Bethesda, Bethesda Softworks, ZeniMax and related logos are registered trademarksor trademarks of ZeniMax Media Inc. in the U.S. and/or other countries. All Rights Reserved.
「ゲームと社会をごちゃまぜにして楽しんじゃえ」がモットーの、フリーのコンテンツ開発者。節電ゲーム「#denkimeter」やVRコンテンツ、体験型エンタメの開発をしています。モニター画面の中だけで完結しないゲーム体験が好きで、ここ十数年注目しているのはアイドルマスターです。