みなさん、こんにちは!High Horse Entertainment の Jay です。ロサンゼルスにある、2 人だけのチームです。我々は、High Horse を最新のグラフィックス、制御スキーム、剛健なオンラインでアーケード ゲームをビルドするために立ち上げました。我々のデビュー タイトル Disc Jam は、タイミングと反射が成功の重要要素となるアーケード アクション スポーツ ゲームです。興味をお持ちの方は、www.discjamgame.com でプレアルファ リリース版用の無料の Steam キーを取得できます!
このプロジェクトでは、Disc Jam を反応が良く流れるようなゲームプレイ スタイルにするために 60 FPS を維持することが必要不可欠だったので、とりわけパフォーマンスに重点を置きました。そして、このフレームレートを目指してアンリアル エンジン 4 を使って、多くのことを習得することができました。Intel の統合型 GPU (グラフィクス プロセス ユニット) を使った体験、およびシステム要件を最小にしたままどのように目標のパフォーマンスを実現したのか、お話を伺いました。
なぜ統合型 GPU をターゲットにしたのですか?
ハードウェアが標準化されていないため、PC 開発はコンソールと比べてやっかいです。ほとんどの人が PC でゲームをプレイします。中には専用のグラフィックス チップを持っている人もいますが、PC 所有者がゲームをするには、ほとんどの場合、統合型 GPU が必要となります。正確な市場規模を把握するのは難しいですが、Unity Technologies による現在のハードウェア統計 によると、マシンのおよそ 40% は Intel の GPU を使用しています。群を抜いた数字です。PC ゲームの多くは非常に少ないシステム要件で済んでいる一方、Disc Jam は 2 つの大きな理由からできるだけ低くスケールすることが重要でした。
同時接続性
Disc Jam のようなマルチプレイヤー ゲームでは同時接続性が楽しさを左右します。誰もプレイしなければ、対戦相手は見つかりませんし、全体が消滅してしまうまでプレイヤーの基盤は縮小します。このため、できるだけ多くのハードウェア構成に対応することが重要なのです。
パフォーマンス
Disc Jam は 60 FPS でプレイするように作られています。60 FPS を維持できないシステム上で誰かがプレイすると、本来予定していたゲームを体験できなくなってしまいます。Disc Jam は何といってもオンライン ゲームなので、チームメイトと敵の体験にも影響を与えます。
アンリアル エンジン 4 の拡張性とパフォーマンス
アプローチを決定する時、対象のハードウェア上で「すぐに使える」アンリアル エンジン 4 のパフォーマンスに注目しました。アンリアル エンジン 4.12.5 のバイナリ リリースとシューティング ゲーム サンプルを使ってそれをテストしました。すべてのテストは Intel® Core™ i7-4720 HQ プロセッサと Intel® HD Graphics 4600 GPU 搭載のラップトップで行いました。Runn
図 1. エピックの品質設定 - ~20fps
図 2. 低品質設定: ~40fps
制作するゲームの目標レートが 30 FPS であればこれで良かったのですが、残念なことに我々は最低 60 FSP を目指していました。シューティング ゲーム サンプルよりも最適化したシーンの開発は難しく、アンリアル エンジン 4 (UE4) デスクトップ レンダラは我々の対象とするハードウェアには基本的なパフォーマンス付加が大きすぎると思いました。クリエイティブになって、若干違うことに手を染めてみてもいいかなと思えるのであれば、UE4 には別の手段があります。
アンリアル エンジン 4 のモバイル プレビュー レンダラ
アンリアル エンジンは、ハイエンドなデスクトップ / コンソール ゲームだけを作り出すだけではありません。ハイエンドなモバイル ゲームだって作れるのです!そのためには、星の数ほど市場に出回っているモバイル デバイスに対応するために、いくつか異なるレンダーパスを備えています。私達がいいなと思ったパスは、OpenGL Embedded Systems (ES) 3.1 + Android Extension Pack (AEP) 用の最もハイエンドなパスでした。このレンダリング パスは、Intel の統合型 GPU では品質とパフォーマンスのベストな比率をマークすることが我々のテストで分かりました。
ここで重要なことは、UE4 にはモバイル プレビュアと呼ばれる機能があることです。この機能は、デプロイしなくてもモバイル デバイスでゲームをプレビューすることでイタレーション時間を短縮します。これにより、アンリアルが通常使用する本格的なディファード レンダラではなく、モバイル レンダリング パスを使ってデスクトップ上でゲームを効果的にレンダリングすることができます。この機能を使うと、このようになります。
図 3. OpenGL ES 3.1 + AEP Mobile Preview: ~100fps
モバイル プレビューで実行すると、速度が最低設定のデスクトップ レンダラの 2.5 倍になります。統合型 GPU 上で目標の 720p @ 60 FPS を実現しました!デスクトップ レンダラとモバイル レンダラで撮ったスクリーンショットを見比べると、差が分かると思います。モバイル レンダラには特にライティングとシャドウイングに制約があるためです。詳細は モバイル プラットフォームのライティング および モバイル デバイスのパフォーマンス ガイドライン のドキュメントを参照してください。
複数のライティング リグ
上記の問題を解決し Disc Jam 内で常にコートを照らすために、複数のライティング リグを使うことにしました。従来のレンダラでレンダリングする場合は 1 つのリグを、モバイル プレビューでレンダリングする場合は別のリグを使います。ライティングのニーズはそれぞれのゲームで異なりますが、Disc Jam は主要なシャドウ キャスティング ライトの可動性以外はすべて同じライト設定を両方に使用しました。ハイエンド版では、主要ライトは Stationary (固定) のスポットライトです。モバイル プレビューでは、ライティングのすべてがプリベイクされ、Static (静的) スポットライトを使いました。
図 4. Disc Jam* ハイエンド レンダラとライティング
図 5. Disc Jam ローエンド レンダラとライティング
UE4 で複数のライト リグを使ってまず最初に、ベイクされたライティングはライトではなくジオメトリと一緒にマップに格納されるという事実に直面します。つまり、すべてのジオメトリを 2 つ目のマップに複製して、ライトのスペアのセットをベイクしなくてはならなのです。
Disc Jam には、ライティングには影響を受けないアクタをすべて配置したパーシスタント レベルを設定してます。これらのアクタはハイエンドとローエンドの両方のマップで共有されて、スポーン ポイントやコリジョン ボリュームを含みます。そうすると、ライティングに同じジオメトリとディファーのみを持つハイエンド マップとローエンド マップができます。レベルをロードすると、正しいバージョンにストリームインします。
図 6. Disc Jam の Persistent Level Blueprint
図 6 で使っている “Is in Mobile Preview” ノードは、C++ 関数を以下のようにカスタムして定義しています。
bool UDiscJamBlueprintFunctionLibrary::IsInMobilePreview() { return GMaxRHIFeatureLevel <= ERHIFeatureLevel::ES3_1; }
パッケージングとデプロイ
注記:以下のセクションでは、Windows でのパッケージングとデプロイについて説明します。次のステップは、他の OS とほとんど同じです。
ゲームをパッケージングして、コマンドライン引数 “-FeatureLevelES31” を実行しようとすると、必要なシェーダーがパッケージ内に含まれていないことがすぐに分かります。Project Settings (プロジェクト設定) → Platforms (プラットフォーム) → Windows → Targeted RHIs を選択すると パッケージするシェーダーを選択するチェックボックスが表示されますが、OpenGL ES 3.1 シェーダーはその中にありません。シェーダーを追加するために、コードを 2 個所変更します。
GenericWindowsTargetPlatform.h で、GetAllPossibleShaderFormats 関数を OpenGL ES 3.1 シェーダーを含むように変更します:
virtual void GetAllPossibleShaderFormats( TArray<FName>& OutFormats ) const override { // no shaders needed for dedicated server target if (!IS_DEDICATED_SERVER) { static FName NAME_PCD3D_SM5(TEXT("PCD3D_SM5")); static FName NAME_PCD3D_SM4( TEXT( "PCD3D_SM4" ) ); static FName NAME_PCD3D_ES3_1( TEXT( "PCD3D_ES31" ) ); static FName NAME_GLSL_150(TEXT("GLSL_150")); static FName NAME_GLSL_430(TEXT("GLSL_430")); OutFormats.AddUnique(NAME_PCD3D_SM5); OutFormats.AddUnique(NAME_PCD3D_SM4); OutFormats.AddUnique(NAME_PCD3D_ES3_1); OutFormats.AddUnique(NAME_GLSL_150); OutFormats.AddUnique(NAME_GLSL_430); } }
次に、WindowsTargetSettingsDetails.cpp で、GetFriendlyNameFromRHIName 関数を変更して UI に表示するために分かりやすい名前を追加します:
FText GetFriendlyNameFromRHIName(const FString& InRHIName) { FText FriendlyRHIName = LOCTEXT("UnknownRHI", "UnknownRHI"); if (InRHIName == TEXT("PCD3D_SM5")) { FriendlyRHIName = LOCTEXT("DirectX11", "DirectX 11 (SM5)"); } else if (InRHIName == TEXT("PCD3D_SM4")) { FriendlyRHIName = LOCTEXT("DirectX10", "DirectX 10 (SM4)"); } else if (InRHIName == TEXT("PCD3D_ES31")) { FriendlyRHIName = LOCTEXT("DirectXES31", "DirectX Mobile Emulation (ES3.1)"); } else if (InRHIName == TEXT("PCD3D_ES31")) { FriendlyRHIName = LOCTEXT("OpenGL3", "OpenGL 3 (SM4)"); } else if (InRHIName == TEXT("GLSL_430")) { FriendlyRHIName = LOCTEXT("OpenGL4", "OpenGL 4 (SM5, Experimental)"); } else if (InRHIName == TEXT("SF_VKES31")) { FriendlyRHIName = LOCTEXT("Vulkan ES31", "Vulkan Mobile (ES3.1, Experimental)"); } else if (InRHIName == TEXT("SF_VULKAN_SM4")) { FriendlyRHIName = LOCTEXT("VulkanSM4", "Vulkan (SM4)"); } else if (InRHIName == TEXT("SF_VULKAN_SM5")) { FriendlyRHIName = LOCTEXT("VulkanSM5", "Vulkan (SM5)"); } return FriendlyRHIName; }
上記 2 点を変更してエンジンを再コンパイルしたら、あとは Windows プラットフォーム設定の中のチェックボックスにチェックを入れるだけです。
図 7. 新規作成された‘DirectX Mobile Emulation (ES3.1)’ の表示
追加オプション:Intel の GPU でモバイル プレビュアを自動的にアクティベートする
Disc Jam では、プレイヤーは Steam 起動オプションを使って、起動時に使用するレンダラを選択することができます。ローエンド レンダラを選択すると、“-FeatureLevelES31" コマンドライン オプションでゲームを開始します。
図 8. Disc Jam Steam 起動オプション
ただし、Intel の GPU の場合、ゲームのデフォルトはモバイル プレビュー レンダラにしています。これもまた別の簡単なコード変更で処理できます。In WindowsD3D11Device.cpp で、関数 FD3D11DynamicRHI::InitD3DDevice() がビデオ アダプターを初期化します。関数の 100 行目あたりで、video メモリを正しく設定するために Interl の GPU を使うかどうかチェックします。ブロック内で、レンダラをそのように設定できます。
if ( IsRHIDeviceIntel() ) { // It's all system memory. FD3D11GlobalStats::GTotalGraphicsMemory = FD3D11GlobalStats::GDedicatedVideoMemory; FD3D11GlobalStats::GTotalGraphicsMemory += FD3D11GlobalStats::GDedicatedSystemMemory; FD3D11GlobalStats::GTotalGraphicsMemory += ConsideredSharedSystemMemory; GMaxRHIFeatureLevel = ERHIFeatureLevel::ES3_1; GMaxRHIShaderPlatform = SP_PCD3D_ES3_1; }
これで終わりです!
お役に立てましたでしょうか?Twitter の @HighHorseGames まで是非ご感想をお寄せください。Disc Jam の情報は http://www.discjamgame.com のブログで随時更新しています。
Intel Developer Zone ブログのオリジナルは こちら からどうぞ。