サンフランシスコで設立され、現在は京都に拠点を置くインディーゲームスタジオ17-BIT。 彼らが昨年リリースしたVRタイトル『Song in the Smoke』は、 PSVRとOculus Questでの同時リリースを実現した意欲作だ。 その技術的な挑戦について寄稿いただいたので紹介する。

※本記事はCGWORLD283号(2022年3月号)の記事を一部再編集したものです

記事の目次
    the English version is available here.

    ●Information

    『Song in the Smoke』

    発売・開発:17-BIT
    価格:2,990円
    リリース:発売中
    Platform:Oculus Quest、Oculus Rift、 PlayStation VR
    ジャンル:アクションアドベンチャー
    www.songinthesmoke.com

    ●Staff

    ウィリアムソン・コリン/Colin Williamson

    リードテクニカルアーティスト(17-BIT)

    山岸宏一/Koichi Yamagishi

    3Dアーティスト(17-BIT)

    宮本アレックス/Alex Miyamoto

    リードエンジニア(17-BIT)

    ハイスペック版とモバイル版を同一のUE4プロジェクトで開発

    『Song in the Smoke』はUnreal Engine 4を使って開発されたVRのサバイバルゲームです。 プレイヤーはアイテムを収穫し、生き物を狩り、 キャンプを張り、各レベルの野獣のボスを倒して次のゾーンに進みます。VRゲームであるため、プレイヤーは収穫したアイテムを使って道具や武器、衣服を作るなど、身体的なインタラクションに重きを置いています。

    本作は、当社17-BITの15人のチームによって開発されました。プロジェクト開始当初は PS4とPCでのみ発売する予定でしたが、開発の中盤で計画を変更し、Oculus Quest(以下、Quest)版も同時に発売する決断をしました。

    われわれの挑戦は、ハイスペックのゲームアセットを、ロースペックのモバイルVR用に全て作り直し、別のブランチを必要とせず全てのデータを同じUE4プロジェクト内に保持し、 3つのバージョンを同じ日に出荷することでした。ゲーム開発では多くの場合、ハイスペック版を完成させた後にモバイル版の移植に移りま すが、この記事はハイスペックとロースペックのUE4ゲームを同時に発売しようとしている開発チームを支援するために書かれたものです。

    グラフィックスの特徴

    本作のグラフィックスは、コンセプトアーティスト・寺田克也氏のアートに沿ったトゥーンシェーダや、距離に応じて霧の色が変化するルックアップテーブルを実装しています。また、 遠くの霧の形状がダイナミックに動くフォグアニメーションシステムも搭載しています。さらに、時間の変化に応じてリアルタイムで様々に天候が変化します。登場する生物はほとんどが四足歩行で、Dragon.IKというミドルウェアを 使ってリアルな足の動きを実現しています。


    また、本作は全てのプラットフォームにおいて、その速度、MSAA(マルチサンプル・アンチエイリアス)のサポート、およびVRヘッドセットでの全体的な画質のために、フォワードレンダリングを採用しています。フォワードレンダリングの欠点は、複数のダイナミックライトが非常に高コストであることです。ほぼ全てのグラフィック要素をQuest用につくり直したので、その過程を紹介しましょう。

    寺田克也氏によるアートの一部

    ハイスペック VS モバイルのレンダリング

    QuestはPCを必要としないスタンドアローンなVRヘッドセットで、モバイル仕様のSoC CPUとGPUを独自に搭載しています。しかし、Questは頂点処理能力がかなり高い反面、厳しい制限も多くあります。さらに難しいのは、最低フレームレートがPS4の60fpsに対して、72fpsであることです。

    Quest版では、OpenGLに比べてCPUの使用が大幅に少ないVulkan Mobileを採用することにしました。Vulkanの欠点は、プレイヤー がプレイ前に一度だけPSO(Pipeline State Object)キャッシュ処理を行う必要があり、最初のプレイに1分以上かかることです。しかし、PSOのキャッシュ生成がないと、新しいマテリアルが シーンに導入されたときに、フレームレートが落ちることがあります。

    また、左目で見たメッシュをインスタンス化し右目で素早くレンダリングすることでCPUオーバーヘッドを低減できる「モバイルマルチビュー」機能や、フレームの中心にピクセルのディテールを集中させる「ダイナミック・フォービエイテッド・レンダリング」も活用しました。

    レンダリング速度を維持するために、いくつかの機能は外しました。モバイルHDRとモバイル・デプス・プリパスは遅すぎたので、無効化しました。

    Challenge 1:半透明

    半透明の描画をできるだけ少なくすることは、 全てのVRに当てはまる正解で、特にモバイルVRはディファードレンダリングを使用し、半透明の描画にはより遅いレンダリングパスを使う必要があります。VRコンテンツでは、ピクセルは可能な限り2回以上描画されるべきではありません。つまり、画面の大部分を占める半透明は、レンダリングの速度を大幅に低下させる可能性があります。複数の大きな透明効果が重なった場合、例えば、半透明な水のメッシュの前に複数のUIウインドウがある場合、フレームレートは最低値以下に低下する可能性があります。

    われわれの解決策は、可能な限り半透明を使用しないことでした。アルファチャンネル要素の多くをビルボードメッシュに変換し、さらにテクスチャのカラーをメッシュの頂点カラーに焼き付けることで、テクスチャの読み込みを不要にしました。ゲーム内のパーティクルのほとんども、不透明なビルボードメッシュです。頂点数の増加は問題にならなかったので、できるものは全てメッ シュに置き換えることをオススメします。

    半透明のエフェクトはレンダリングが遅いので、UIのパーツは半透明アルファテクスチャ付き四角形から不透明のメッシュに変換しました

    Challenge 2:シンプルなマテリアル

    本作のPS4用マテリアルの多くは複数のテクスチャや複雑なレイヤーブレンディングなど、モバイルGPUで動作するように設計されていない、非常に複雑なものでした。われわれが最初に行なった作業のひとつは、同じシェーダ内に複数のマテリアルバージョンを内包 させ、使用するプラットフォームに応じて動的に切り替えるシステムを構築することです。これは、マテリアル関数によって2つの入力をシェーディングパススイッチに送ることで簡単に実現できました。

    これにより、アーティストは同じマテリアル内にハイスペック版とロースペック版の両方を含めることができるようになりました。エディタ内で結果をプレビューするには、ツールバーの[Vulkan Preview]をクリックするだけです
    実装はこのようになります。このマテリアルはPS4で赤色、Questで緑色で表示されます。注意:この方法では、マテリアル・ドメインまたはブレンド・ノードは変えられません。例えば、ブレンド設定をPS4版では透明、Quest版では不透明にといった切り替えはできません

    このシンプルなマテリアル関数のおかげで、各プラットフォームに合わせて使用するマテリアルを変更することができました。ハイスペックなプラットフォームでは、スプラットマップ、ハイトマップブレンディ ング、地形レイヤーの複数の詳細テクスチャを使用することができ、 ロースペックでは、メッシュ頂点カラーを使用して、単一のテクスチャの単純な色合いでブレンドを制御しています。



    UE4がコンテンツを最終的なパッケージに変換する際、現在のプラットフォームに関連しないデータは全て除外されるため、他のプラットフォームからのデータの肥大化によってパッケージサイズが増大するリスクはありません。

    Challenge 3:プラットフォームLOD

    ゲームに登場する敵キャラクターの多くは、最高精細度のLOD0モデルで1万5,000~2万ポリゴン。アルファマスク付き透明のマテリアルを使う要素もあるため、モバイルVRではパフォーマンスが発揮できません。

    この問題を解決するために、当社のキャラクターアーティストは、敵キャラクターの3,000ポリゴンのローモデルと、代替となる不透明なマテリアルを作成しました。次に、これらのバージョンを敵キャラクターのスケルタルメッシュのLOD1スロットに手動でインポートし、LOD1マテリアルを上書きして不透明なマテリアルを使用するようにしました。最後に、AndroidのMinimum Lodを1に設定し、QuestがLOD0をスキップしてLOD1を使うようにしました。

    PS4 LOD(左)とQuest LOD(右)。Quest版は使用ポ リゴン数が少なく、不透明マテリアルを使っています

    また、われわれはこの方法をスタティックメッシュにも適用し、スタティックメッシュにローポリゴンと不透明なマテリアルの上書きが必要な場合に、これによりLODパッキングを行うことができました。一般的な目安としては、LOD0を PS4版、LOD1をQuest版として使用します。

    [Minimum LOD - Android]を1に設定すると、そのプラットフォームのLOD1モデルが自動的に適用されます

    Challenge 4:ライティングとムービーシーン

    フォワードレンダリングを採用したことで、本作のライティング処理には劇的な変化がありました。本作では、以下の3つのライトを使った時間経過システムを採用しています。


    ①ディレクショナルライト1:太陽ライト(固定シャドウ)

    ②ディレクショナルライト2:フィルライ(シャドウなし。これはトゥーンシェーダのノーマルを見やすくするために意図的に)

    ③スカイライト:シンプルなアンビエント(シャドウなし。シャドウは100%の黒にはならないようにする)


    強度や色味はテーブルで制御し、時間の経過と共に値が滑らかに補間されます。

    1日の時間による変化。左から朝、真昼、夕焼け。事前に計算されたライト マップを朝、午後、夕焼けの3種類準備しました。夜は「午後」を暗くして再利用しています

    Questでの複数のディレクショナルライトのレンダリングは遅すぎたので、1つのポイントライトで複数のシャドウを投影する低レベルのハックを実装する必要がありました。フォワードレンダリングで動的なライトをレンダリングするには膨大なコストがかかるため、本作では一度に1つのダイナミックライトに制限し、減衰半径を小さく抑えています。ダイナミックライトは、キャンプファイヤー、松明、発光する棍棒の上部にのみ使いました。

    もうひとつの問題は、画面の大部分を占める動的なオブジェクトにダイナミックライトを当てると、レンダリングが遅くなったことでした。この問題は、動的なオブジェクトにライティングをベイクし、マテリアルをUnlitに設定することで解決しました。

    マントは、プレイヤーが全てのアイテムを収納する場所です。これはダイナミックライトで照らすとレンダリングが遅くなりすぎるので、ライティングをベイクする必要がありました

    さらに残念なことに、ダイナミックシャドウのレンダリングにも非常に限界がありました。キャラクターには、UE4のカプセルシャドウが使用されており、これは非常に高速ですが、本作でのダイナミックなシャドウはこれだけです。Quest版には単純にシャドウはありません。

    カプセルシャドウ。レンダリングが安っぽい

    ゲーム内のムービーシーンは、不思議な小屋の中のベッドで体験する夢で構成されています。この夢はゲームに神秘的な感覚をもたらし、次に何をすべきかのヒントをプレイヤーに与えてくれます。これらのシーンでは、LODパッキングを利用してプラットフォームに応じて簡単にモデルを交換することができましたが、ライティングで大きな問題に直面しました。PS4のライティングリグは、Vulkanでレンダリングすると正しく表示されず、特定のライトタイプはモバイルでもサポートされていませんでした。

    PS4(左)とQuest(右)のライティングリグ。各プラットフォームは別々のライトセットを使用します
    Questのムービー シーンは、厳しい制約のため、ダイナミックライトとディレクショナルライトが1つずつに限られていました

    解決策は、ライトを別々のサブシーン(High QualityとLow Quality)に分離し、PS4とQuestのどちらで実行されているかによって、正しいサブシーンを再生するコードをシーケンサーに導入することでした。なお、ライトの重複はVRのパフォーマンスを低下させるので、これらのシーンでは全てのライトを初期状態で「Deactivated」に設定する必要があります。この機能により、PS4では高品質なライティングを維持しつつ、モバイル版ではパフォーマンス性の高いライティングに集中することができました。

    UE4のシーケンサーでは、ハイスペックとロースペックのライティングリグが別々のサブシーンとして表示されます

    Challenge 5:ドローコールとレベルデータ

    ドローコールに厳しい制限があるため、レベル変換は、個々のモデルをローポリゴンに置き換えるよりも遥かに難しい作業でした。

    本作の各レベルは巨大です。各マップは最大1km四方で、複数のストリーミングゾーンがあります。レベルのアセットは主に地形と8種類の岩石で、それらを様々に組み合わせています。最大のレベルである“Cathedral (大聖堂)”には、何千という岩石のメッシュがあります

    PS4版では、UE4はくり返されるメッシュを自動的にインスタンス化するのが得意なので、ドローコールの回数に問題はありませんでした。本作では、毎フレーム250~450回のドローコールをして、何千もの個別のレベルメッシュを描画します。しかしQuest版ではメッシュの自動インスタンス化が利用できず、1フレームあたり150回のドローコールの制限があったため、2つの目標を立てました。ひとつはメッシュの合体と手動インスタンス化により、レベル内のメッシュ数を大幅に削減すること、もうひとつは全体的なポリゴン数の削減です。

    UE4には、アクタのマージやHLODといった優れたメッシュ合成機能がありますが、合成されたメッシュを作成する際には、よりきめ細かいコントロールが必要でした。そこで、The Forgeというパートナースタジオと協力して、メッシュを賢くグループ化し、タグで特定のメッシュを除外し、メッシュの「バケット」を簡単に作成できるツールを作成しました。

    最も重要なのは、The Forgeのツールは、合成する前にオリジナルのコリジョンメッシュを抽出できたことです。これにより、Quest版のレベルはPS4版と同一のプレイヤーコリジョンをもつことができ、AIとナビメッシュのバグを減らすことにつながりました。

    Custom Actor Mergingツール。合成するメッシュを選択
    合成されたメッシュの例。ほとんどの合成されたメッシュは、トータル4レベルのLODがあり、3,000~5,000ポリゴンでした。最大のサブレベ ルでは、この合成処理によって、1,200メッシュあったレベルのメッシュ数を、Quest版では87メッシュまで減らすことができました 
    各色は個々のメッシュを表しています。左:PS4レベル、右:Questで合成したレベル

    最後に、The Forgeにマテリアル置き換えツールを作成してもらい、レベルを通して、あるタイプのマテリアルを全て別のタイプに置き換えることができました。これは先述のプラットフォームごとのマテリアル手法では解決できない、水面や樹冠などの透明なマテリアルを不透明なマテリアルに変更しなければならない場合に便利でした。

    マテリアル置き換えツール

    左:PS4版、右:Quest版。アルファマスク付き透明のマテリアルは不透明なマテリアルに置き換える必要が あり、水のマテリアルはAdditiveマテリアルを使用するように簡略化されています

    残念ながら、PS4版とQuest版のレベルデータを同じマスターレベル内に格納することはできませんでした。そのため、Quest版のマスターレベルを作成し、Level GeometryサブレベルをQuest Level Geometryサブレベルに置き換える必要がありました。

    マスターとQuest版のレベル、サブレベル構成

    Challenge 6:インスタンス

    前項で述べたように、自動インスタンス化はUE4の最も便利なレンダリング機能の1つです。シーン内の複製されたメッシュは自動的に1つのインスタンスにまとめられ、1回のドローコールでレンダリングが行われます。しかしながら、この機能は、モバイル版では利用できませんでした。

    インスタンスはVulkanでもサポートされていますが、手動で行う必要があります。このため、エンジニアチームは、プレイヤーのアイテムのメッシュを自動的にインスタンス化するプログラムの作成にかなりの時間を費やしました。また、プレイヤーがクラフトシステムを使っているときに、シーンの裏でメッシュを合成することも必要とされました。

    次に、木の幹や樹冠のようなくり返しメッシュを自動的にインスタンス化するツールを作成しました。これにより、数百回あったドローコールを一桁台に減らしました。また、LOD を使いすぎないように注意する必要もありました。LODを増やすと、状況によってはシーンに余分なドローコールを追加することになるからです。幸いなことに、UE4のFoliageツールは、期待通りにメッシュをインスタンス化し、修正を必要としませんでした。

    各カラーオブジェクトは手動でインスタンス化されたメッシュで、レンダリング前に1つのドローコールにされています

    Challenge 7:オクルージョン

    ドローコールが1フレームあたり120~150回に厳しく制限されて いたため、不要なメッシュは描画しないようにしなければなりません。たった1回のドローコールですら減らすことは常に重要なので、オクルージョンと可視性にこだわる必要がありました。幸いなことに、 UE4には、視界から外れたメッシュを隠す様々なオクルージョン機能が用意されており、そのほとんどを使用しました。

    まず、レベル内の、プレイヤーが移動可能な範囲に事前計算されたビジビリティボリューム(Precomputed Visibility Volume)を配置しました。各レベルの[World Settings]で、[Precomputed Visibility Aggressiveness]を[Most Aggressive]に設定すると、精度は落ちますが(一部のメッシュが飛び出すことがある)、ドローコールが大幅に減少しました。

    青いボックスは、事前計算されたビジビリティゾーンを表し、ロースペックのパフォーマンスを大幅に向上さ せることができます

    次に、インスタンスメッシュ(樹木や樹冠など)は他のオブジェクトを遮らず、ドローコールが増大してしまうことがわかったので、各樹木の内部にもうひとつ「Hidden In Game」に設定したメッシュを追加する必要がありました。

    r.visualizeoccludedprimitivesというコマンドを使うと、オクルージョンがどのように機能しているのかがよくわかります

    次に、Blueprint内のメッシュの最大描画距離が約200mに設定されていることを確認しました。ワールド内のダイナミックオブジェクトは事前計算されたオクルージョンの影響を受けないので、遠くにあるときに描画しないように値を手動で入力する必要があります。パーティクルもデフォルトで無限遠でレンダリングされるため、最大描画距離を設定しなければなりません。GPUパーティクルは余分なオーバーヘッドを与えるモバイルでは使用しないでください。

    ドローコールのリストをチェックし、ゲームをプロファイリングするには、Renderdocを使用するのがオススメです。これにより、Questからキャプチャしたフレームを1枚ずつ描画し、描画時間をチェックして、どのドローコールに時間がかかりすぎているかを正確に確認することができます。また、何らかの理由でシーンに表示されている不正なオブジェクトを探し出すこともできます。

    Renderdocでは、シーン内の全てのオブジェクトをステップごとに見ていくことができます

    ハイスペックからモバイルへの大きな変更点として、プレイヤーのアイテムが入っているインベントリのシステムが挙げられます。プレイヤーが収納マントを開くと、プレイヤーアイテムが個別のメッシュとして表示されますが、モバイルでレベルをその背景に表示するにはドローコールの回数が多すぎました。そこで、プレイヤーの周囲に不透明なバブルを出現させて視界を遮りつつ、フレームレートを低下させることなくアイテムを操作できるようにする必要がありました。これは、モバイルでやらなければならない最大の妥協点でした。

    Challenge 8:ポストプロセス

    本作では、ポストプロセス効果を多用しています。カスタムデプスを使ってキャラクターのアウトラインエフェクトを描き、夜間には画像 をわずかに脱色しています。

    PS4では、動くフォグのエフェクトも用意しました。これは回転するキューブマップをワールド空間に投影し、SphereMaskで範囲を絞ることで作られています。さらにまた別のSphereMaskを使用して、色付きのライトをフォグに追加しています。このエフェクトは見た目も良く、処理も軽いので、ぜひ試してみてください。

    最終的なコンポジット(左)とポストプロセス効果用のカスタムデプス(右)の出力

    残念ながらQuestではポストプロセスが利用できず、ポストプロセス命令は無視されるだけです。アウトラインエフェクトやフォグを再現するために「インサイドアウト」の考え方を採用し、エフェクトを各オブジェクトの一部としてレンダリングしました。

    これはQuest用のアウトラインエフェクトはキャラクターマテリアルに絞り込んだフレネル効果を与えることで実現し、フォグはWorld Aligned Noise Pannerのマテリアル関数を作成し、これらをレベルで使用されている全てのマテリアルに追加しています。

    Questのフォグエフェクト。これはインサイドアウト方式で動作し、各オブジェクトのマテリアルの中にレンダリングされます。透明度やオーバードローはありません

    もうひとつ、ポストプロセスが利用できないため、実際、ゲーム中で黒にフェードアウトすることはありません。その代わり、プレイヤーカメラの上に球体を出現させ、それをどんどん小さくしていき、シーン内の全てをブラックアウトさせています。安直なエフェクトですが、効果は絶大です。

    フェードアウトエフェクトの例

    最後に

    大規模なゲームをPCとモバイルVRで同時に出荷することには、メリットがあります。しかしながら同時開発には、アセット作成時に細心の注意を払い、常にハイスペックとモバイルの双方を意識した開発を行う必要があります。

    しかし、その過程で発見されたCPUやGPUの最適化手法は、パフォーマンスに大きく貢献します。プロジェクト終了時には、モバイル版のために多くの最適化が行われたため、ハイスペック版は予想以上に速く、高い解像度で動作していました。

    VRゲームの開発は、何千もの小さな最適化の積み重ねです。 1つの変更は0.5%の改善かもしれませんが、最終的にはそれが積み重なって大きな進歩になります。同じ挑戦をしようとしている全ての開発者の幸運を祈ります!

    TEXT_ウィリアムソン・コリン、山岸宏一、宮本アレックス(17-BIT)
    EDIT_小村仁美 / Hitomi Komura(CGWORLD)