2Dゲームの大きなビデオメモリ要件をどのように解決しますか?


40

2Dゲームの大きなビデオメモリ要件をどのように解決しますか?


Allegro C / C ++で2Dゲーム(Factorio)を開発していますが、ゲームコンテンツの増加に伴い、ビデオメモリ要件が増加するという問題に直面しています。

現在、最初に使用される画像に関するすべての情報を収集し、これらの画像を可能な限りすべてトリミングして、可能な限り緊密に大きなアトラスに整理します。これらのアトラスはビデオメモリに保存され、そのサイズはシステムの制限に依存します。現在、通常は最大8192x8192の2つの画像であるため、256Mb〜512Mbのビデオメモリが必要です。

このシステムは、カスタム最適化とレンダリングスレッドと更新スレッドの分割により、60 fpsで何万枚もの画像を画面に描画できるため、非常に有効です。画面には多くのオブジェクトがあり、大きなズームアウトを許可することが重要な要件です。さらに追加したいので、ビデオメモリの要件に問題が発生するため、このシステムは保持できません。

私たちが試したかったことの1つは、最も一般的な画像を含む1つのアトラスと、キャッシュとしての2つ目のアトラスを持つことです。画像は、必要に応じてメモリビットマップからそこに移動されます。このアプローチには2つの問題があります。

  1. allegroでは、メモリビットマップからビデオビットマップへの描画が非常に遅くなります。
  2. allegroのメインスレッド以外でビデオビットマップを操作することはできないため、実際には使用できません。

追加の要件は次のとおりです。

  • ゲームは決定論的である必要があるため、パフォーマンスの問題や読み込み時間によってゲームの状態が変わることはありません。
  • ゲームはリアルタイムであり、すぐにマルチプレイヤーにもなります。どんなコストでも最小のスタッターでさえ避ける必要があります。
  • ゲームのほとんどは、1つの連続したオープンワールドです。

このテストは、1x1から300x300までのサイズのバッチで、構成ごとに数回、10,000個のスプライトを描画することで構成されていました。Nvidia Geforce GTX 760でテストを行いました。

  • ソースビットマップが個々のビットマップ(アトラスバリアント)間で変更されていない場合、ビデオビットマップからビデオビットマップへの描画はスプライトごとに0.1usかかりました。サイズは関係ありませんでした
  • ビデオビットマップからビデオビットマップへの描画、ソースビットマップの描画間での切り替え(非アトラスバリアント)は、スプライトごとに0.56usかかりました。サイズも関係ありませんでした。
  • メモリビットマップからビデオビットマップの描画は本当に疑わしいものでした。1x1から200x200のサイズはビットマップあたり0.3usかかったので、それほどひどく遅くはありません。サイズが大きくなると、201x201の9usから291x291の3116usへと、劇的に時間の増加が始まりました。

アトラスを使用すると、パフォーマンスが5倍に向上します。レンダリングに10ミリ秒かかっていた場合、アトラスを使用すると、フレームあたり100,000スプライトに制限され、それなしでは、20000スプライトの制限があります。これには問題があります。

また、シャドウのビットマップ圧縮と1bppビットマップ形式をテストする方法を探していましたが、Allegroでこれを行う方法を見つけることができませんでした。


1
あなたのゲームの大ファン、私はIndiegogoキャンペーンを支援しました。私は数ヶ月ごとにそれをどんどん食べます。これまでのところ、いい仕事です!サイトのトピックから外れている「どのテクノロジーを使用するか」という質問を削除しました。残りの質問はまだかなり広いので、もっと具体的なことがあれば、範囲を狭めてみてください。
マイケルハウス

手助けありがとう。それでは、どのテクノロジーを使用するかを尋ねる場所はどこですか?特定のエンジンの推奨事項についての答えを探しているわけではありませんが、2Dエンジンの詳細な比較を見つけることができず、パフォーマンスとユーザビリティテストを含む1つずつ手動で検査するには時間がかかります。
マーウィン

「使用する技術」などの質問をする場所については、このページの下部をご覧ください。完全に妥当で合理的な質問がありますが、このサイトで扱っている質問の種類ではありません。特定のエンジンを探していなくても、それが「Xを実行するテクノロジーはありますか?」という質問に答える唯一の方法です。誰かが「はい」と答えて、特定の推奨事項を提示することはできませんが、それはあまり役に立ちません。頑張ってください!
マイケルハウス

2
テクスチャを圧縮していますか?
GuyRT

3
@Marwin、圧縮テクスチャは、必要なメモリ帯域幅を削減するため、非圧縮テクスチャよりもはるかに優れたパフォーマンスを発揮します(これは、帯域幅がはるかに低いモバイルプラットフォームで特に当てはまります)。テクスチャを圧縮するだけで、大量のメモリを節約できます。実際、唯一の欠点は、必然的に導入されるアーティファクトです。
GuyRT 14

回答:


17

RTS(KaM Remake)でも同様のケースがあります。すべてのユニットと家はスプライトです。ユニットと家と地形用に18,000個のスプライトがあり、さらにチームカラー用に別の〜6000個のマスクがあります(マスクとして適用されます)。長く引き伸ばされて、フォントで使用される〜30,000文字もあります。

したがって、使用しているRGBA32アトラスに対していくつかの最適化があります。

  • 最初にスプライトプールを多くの小さなアトラスに分割し、他の回答で説明されているようにオンデマンドで使用します。また、各アトラスに対して個別に異なる最適化手法を使用できます。無駄なRAMが少し少なくなるのではないかと思います。このような巨大なテクスチャにパックすると、通常は下部に未使用の領域があります。

  • パレットテクスチャを使用してみてください。シェーダーを使用する場合、シェーダーコードでパレットを「適用」できます。

  • RGBA8の代わりにRGB5_A1を使用するオプションを追加することを検討します(たとえば、チェッカーボードの影がゲームに適している場合)。可能な場合は8ビットAlphaを避け、RGB5_A1または同等の形式(RGBA4と同様)を使用してください。スペースが半分になります。

  • スプライトをアトラスにしっかりとパックしていることを確認し(ビンパッキングアルゴリズムを参照)、必要に応じてスプライトを回転させ、菱形スプライトの透明なコーナーをオーバーラップできるかどうかを確認します。

  • ハードウェア圧縮形式(DXT、S3TCなど)を試すことができます-RAM使用量を劇的に削減できますが、圧縮アーチファクトを確認できます-一部の画像では、違いが目立たない場合があります(最初の箇条書きで説明したように、これを選択的に使用できます)。しかし、いくつか-非常に発音します。圧縮形式が異なると、アーティファクトも異なるため、アートスタイルに最適なものを選択できます。

  • 大きなスプライト(もちろん手動ではなく、テクスチャアトラスパッカー内)を静的な背景スプライトとアニメーションパーツ用の小さなスプライトに分割することを検討してください。


2
DXTを使用するための+1、それは非常に良いことです。圧縮率が高く、GPUによって直接使用されるため、オーバーヘッドは最小限です。

1
私はdxtに同意します。また、DXT7サポート(DX11 +ハードウェア)を照会することもできます。DXT1は、DXT1と同じサイズですが、(明らかに)より高い品質です。ただし、テクスチャを2倍(DXT7とDXT1)にするか、ロード中に圧縮/解凍する必要があります。
Programmdude

5

まず、より多くの小さなテクスチャアトラスを使用する必要があります。テクスチャが少ないほど、メモリ管理が難しくなります。アトラスサイズを1024にすることをお勧めします。この場合、2ではなく128のテクスチャがあり、2048の場合は32のテクスチャがあり、必要に応じてロードおよびアンロードできます。

ほとんどのゲームは、レベル境界を持つことでこのリソース管理を行いますが、ロード画面には、次のレベルで不要になったすべてのリソースがアンロードされ、必要なリソースがロードされます。

もう1つのオプションは、オンデマンドロードです。これは、レベルの境界が望ましくない場合、または単一のレベルでも大きすぎてメモリに収まらない場合に必要になります。この場合、ゲームはプレイヤーが将来見るものを予測し、それをバックグラウンドでロードしようとします。(例:現在、プレイヤーから2画面離れているもの。)同時に、もう長時間使用されなかったものはアンロードされます。

ただし、1つの問題があります。ゲームが予測できなかった予期しないことが発生した場合はどうなりますか?

  • 必要なものがすべて読み込まれるまで、読み込み画面をパニックして表示します。これは、体験を混乱させるかもしれません。
  • プリロードされたすべてのものに低解像度のスプライトを用意し、高解像度のスプライトの読み込みが完了したらすぐにゲームを継続して置き換えます。これは、プレーヤーにとって安っぽく見えるかもしれません。
  • ゲームプレイに影響を与え、必要な限りイベントを遅らせます。例えば、グラフィックがロードされるまでその敵をスポーンさせません。その戦利品のすべてのグラフィックがロードされる前などに、その宝箱を開けないでください。

省略した要件の一部を追加しました。読み込み画面、またはあらゆる種類の読み込みはできません。レンダリングの準備とゲームの更新で通常はほとんどの時間を既に使用していますが、すべてをバックグラウンドで実行するか、個々のティックの間で実行する必要があります(各ティックは15ミリ秒未満)。とにかく、小さな部品に分割すると、切り替えにある程度の柔軟性が追加される場合がありますが、確実に高速になります。問題は、描画中にソースビットマップを切り替えるとレンダリングが遅くなるため、レンダリング時のパフォーマンスがどの程度低下するかです。正確に測定して、どれくらいかを言う必要があります。
マーウィン14

@Marwinパフォーマンスへの影響はありますが、2Dを扱っているので、2Dが問題になるのはまだ遠いはずです。レンダリングが現在1フレームあたり1ミリ秒かかり、より小さいテクスチャを使用することで突然2ミリ秒かかる場合、それは一貫した60 FPSに達するのに十分な速さです。(
APIビースト14

@Marwin Multiplayerはトリッキーなビジネスであり、常にそうであり、常にそうです。おそらくそこで妥協する必要があります。インターネット経由でデータを転送する必要があるため、パッケージが失われ、pingが突然スパイクするなどの理由で、スタッターが発生します。いつ待つべきか、他のプレイヤーを待つ方法を知る。
API獣14

こんにちは、マルチプレイヤーではst音はほとんど回避できます。私たちは現在その分野で取り組んでおり、良い計画があると思います。後で詳細に調査した内容を説明する自分の質問を投稿して回答することもできます:)驚くかもしれませんが、レンダリング時間は実際には問題です。レンダリングを高速化するために多くの最適化を行いました。メインレンダーは、個別のスレッドおよびその他の小さな調整で作成されるようになりました。忘れないでください、最大ズームでは、プレーヤーは同時に何万ものスプライトを簡単に見ることができます。そして、さらに高いズームレベルを後で許可したいとさえ思っています。
マーウィン14

@Marwin Hm、10kオブジェクトは、適切なバッチ処理を使用する場合、通常、PCまたは最新のラップトップでは問題になりません。レンダリングコードのプロファイルを作成しましたか?
API獣

2

うわー、それは私が推測する3Dモデルから生成された膨大な量のアニメーションスプライトですか?

このゲームを生の2Dで作成するべきではありません。遠近法を修正すると面白いことが起こります。事前にレンダリングされたスプライトと背景を、一部のゲームで頻繁に使用されているライブレンダリングされた3Dモデルとシームレスに混在させることができます。あなたがそれをする最も自然な方法のように思われるそのような素晴らしいアニメーションが欲しいなら。3Dエンジンを取得し、アイソメトリックパースペクティブを使用するように構成し、スプライトを引き続き使用するオブジェクトを、画像を含む単純な平面としてレンダリングします。また、3Dエンジンでテクスチャ圧縮を使用することもできますが、それだけでも大きな前進です。

ほぼすべてのものを同時に画面に表示できるので、ロードとアンロードがあなたにとって大きな役割を果たすとは思いません。


2

まず、RGBA4444、DXT圧縮など、ゲームのビジュアルに満足しながらできる最も効率的なテクスチャ形式を見つけます。DXTアルファ圧縮画像に生成されるアーティファクトに満足できない場合は、実行可能ですアルファの4ビットまたは8ビットのグレースケールマスキングテクスチャと組み合わせた色のDXT1圧縮を使用して、画像を不透明にしますか?GUIのRGBA8888にとどまると思います。

あなたが決めたフォーマットを使って、物を小さなテクスチャに分割することを提唱します。常に画面上にあるため常に読み込まれるアイテムを決定します。これは地形とGUIアトラスかもしれません。次に、通常一緒にレンダリングされる残りのアイテムを可能な限り分割します。PCで最大50-100のドローコールを行ってもパフォーマンスが低下しすぎるとは思いませんが、間違っている場合は修正してください。

次のステップは、上記の誰かが指摘したように、これらのテクスチャのミップマップバージョンを生成することです。それらを単一のファイルに保存するのではなく、別々に保存します。したがって、最終的に各ファイルの1024x1024、512x512、256x256などのバージョンになり、表示したい詳細の最低レベルに達するまでこれを行います。

個別のテクスチャができたので、現在のズームレベルのテクスチャをロードし、使用されていない場合はテクスチャをアンロードする詳細レベル(LOD)システムを構築できます。レンダリングされるアイテムが画面上にない場合、または現在のズームレベルで必要でない場合、テクスチャは使用されません。更新/レンダリングスレッドとは別のスレッドで、テクスチャをビデオRAMにロードしてみてください。必要なテクスチャがロードされるまで、最低のLODテクスチャを表示できます。これにより、低ディテール/高ディテールテクスチャ間の切り替えが表示される場合がありますが、これは、マップ全体を移動しながら非常に高速なズームアウトとズームインを実行する場合にのみ発生すると考えられます。現在のメモリの制約内で可能な限り人が移動またはズームしてロードする場所を事前にロードして、システムをインテリジェントにすることができます。

それは私がそれが役立つかどうかを確認するためにテストするようなものです。LODシステムが必然的に必要になる極端なズームレベルを取得することを想像します。


1

最善のアプローチは、テクスチャを多くのファイルに分割し、必要に応じてロードすることだと思います。おそらくあなたの問題は、完全な3Dシーンに必要な大きなテクスチャをロードしようとしていて、そのためにAllegroを使用していることです。

大きなズームアウトを適用するには、ミップマップを使用する必要があります。ミップマップは、オブジェクトがカメラから十分離れているときに使用されるテクスチャの低解像度バージョンです。つまり、8192x8192を4096x4096として保存し、次に2048x2048として保存し、画面上のスプライトが小さいほど低い解像度に切り替えることができます。両方を別々のテクスチャとして保存するか、ロード時にサイズを変更できます(ただし、実行時にミップマップを生成すると、ゲームのロード時間が長くなります)。

適切な管理システムは必要なファイルをオンデマンドでロードし、誰も使用していないときにリソースを解放します。リソース管理はゲーム開発における重要なトピックであり、管理を単一のテクスチャへの単純な座標マッピングに縮小しているため、管理がまったくない状態に近くなっています。


1
ファイルに分割するということは、HDD上のファイルを意味しますか?私は、すべての写真を手始めにRAMに保存でき、メモリビットマップからビデオビットマップへのコピーでさえも遅すぎると思いますので、HDDからの読み込みはさらに遅くなります。VRAMで最大の解像度を持っているので、mimpapsを使用しても役に立ちません。
マーウィン

ええ、すべてをロードする必要はありません。使用するものだけをロードする必要があります。VRAMにロードされたテクスチャのピクセルを変更するときはいつでも、システムは全体のテクスチャをRAMに移動する必要があります。1つのピクセルを変更するために、VRAMに戻すだけです。すべてを1つのテクスチャに収める場合、256 MBをRAMに移動してから再びVRAMに戻すことで、コンピューター全体がロックされます。異なるファイルとテクスチャで分離するのが正しい方法です。
パブロアリエル

メモリへのコピーとRAMへのコピーをトリガーするテクスチャの変更は、永続的なビットマップにのみ適用され、キャッシュは永続的に設定されない可能性があり、唯一の欠点は、表示が失われた/見つかったときに更新する必要があることです。しかし、アレグロでは、640x480の画像をvramからメモリビットマップに簡単にコピー(ゲームのプレビューを保存)するのに非常に長い時間がかかります。
マーウィン

1
描画自体を最適化するには、すべてを1つの大きなテクスチャに入れる必要がありますが、個々のスプライト間でコンテキストを切り替えると、少なくともアレグロではレンダリング方法が遅くなりすぎます。誤解しないでください。しかし、この質問で私が求めていることを漠然と提案しているので、あなたはここで明らかなキャプテンです。
マーウィン

1
これらのミップマップされたテクスチャを異なるファイルに持つと、プレイヤーがズームインしたときにすべてのアトラスをリロードすることを余儀なくされます。
マーウィン

0

zlibで圧縮し、各アトラスの圧縮からストリーミングできるアトラスファイルをさらに作成することをお勧めします。アトラスファイルとサイズの小さいファイルを増やすことで、ビデオメモリ内のアクティブな画像データの量を抑えることができます。また、トリプルバッファメカニズムを実装して、各描画フレームをより早く準備し、画面にスタッターが表示されないように、より速く完了する機会を確保します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.