XNAで大規模な地形をレンダリングする効率的な方法


10

プレイヤーに大きなスペースを必要とするXNAゲームを作成しています。現在、私が使用しているテスト高さマップは4096x4096で、4ビットBMPとして保存されています。

私がやろうとしているのは、その巨大なハイトマップファイルを取得して、ゲームでレンダリングすることです。私が遭遇している問題は、利用可能なメモリの大部分を使用するため、テレイン全体を一度にメモリにロードするのは非効率的であるという事実です。

私が遭遇したもう1つの問題は、XNA内でハード制限が設定されているため、1つのプリミティブでテレインをすべてレンダリングできないことです。

そうは言っても、私はいくつかの解決策に出くわしましたが、それらすべてを以下にリストしました:

  • 現在のユーザーの位置に基づいたレンダリング-基本的に、ユーザーが世界中のどの方向を向いているかに関係なく、ユーザーの周りに正方形を描画します。ユーザーが表示しないスペースをレンダリングしているため、これも私が望んでいたものとは異なります。
  • ユーザーの向きと位置に基づいたレンダリング-ハイトマップのどのピクセルがレンダリングされることになっているはずの三角形を取得する式を見つけましたが、これは非常に難しいことが判明しました。
  • テレインを複数のチャンクに分割し、どのチャンクがユーザーに最も近いかをレンダリングします-まだ人々に表示されないチャンクをレンダリングしているため、まだあまり効率的ではありません。そして、高さマップをいくつかに分割する必要があり、スケーラビリティが大きな問題になるため、これは作業集約型です。

それらの解決策を試した後、私は何をすべきかについての考えが新鮮です。人々がこれらの複雑なアルゴリズムを実行するように言われているいくつかの回答を受け取りましたが、私はそれらを行う方法にさえどうしてもわからないだけです。

したがって、基本的に私はXNAで巨大な地形を最大限の効率でレンダリングするシンプルで簡単な方法を求めています。

私はゲーム開発全般については初心者ですが、それが有望であると思われる場合は、調査に応じます。

更新1: geoclipmappingメソッドを調査した後、私はそれでコーディングを始めました。私はすべての数学を終えて、ゲームが実行されます。しかし、それは非常に非効率的です-これはおそらく私の側の悪いコーディングです。それは2FPSで実行され、私のCPUのコア全体を使用します。コードを改善するつもりですが、さらにサポートが必要になると思います。TerrainマネージャークラスのコードのPastebinを次に示します。より効率的になった場合は、後でさらに結果を投稿します。


1
興味深いことに、あなたが話している手法は、ID Softwareが次のゲームRageで使用している手法に似ているようです。彼らは「メガテクスチャ」を使用し、GPUに必要な部分をストリーミングします。彼はそれについての話をしましたが、ウィキペディアの記事がここにあります、それはインスピレーションを与えるかもしれません:en.wikipedia.org/wiki/MegaTexture

回答:


5

通常、チャンクアプローチが使用されます。何十万もの三角形をテストして、レンダリングする必要があるかどうかを確認することは、めったに効率的ではありません。代わりに、ほとんどの地形レンダリングアルゴリズムは、空間データ構造を使用して、地形の可視部分を動的にレンダリングします。

実装が簡単なデータ構造はquadtreeと呼ばれます。要するに、クワッドツリーを使用するには、プレーヤーの視錐台を見つけ、それをクワッドツリーの最上位と交差させ、部分的に見えるチャンク(つまり、錐台平面がチャンクと交差する)について、すべての子を細分割してテストしますチャンク、錐台の外のものは省略します。これにより、数レベルの再帰のみで、実際に表示されるジオメトリにかなり近づきます。

より高度なテレインレンダラーは、アルゴリズムを使用して、表示可能なジオメトリだけでなく、そのジオメトリの詳細も調整します。現在のところ、Geomipmapping(およびその相対的なgeoclipmapping)は、そのために比較的人気がありますが、実装するのは簡単なことではありません。

編集: ここでは geoclipmappingと錐台カリングの両方のまともな説明があります。

また、高さマップの4ビットが、結果に対して多くの平滑化を行わない限り、見栄えの良い地形を生成するのに実際に十分であるかどうかについても疑問があります。


私はその記事を見て、大量の地形を表示するのに最も効率的であるように思われるので、最初にgeoclipmappingメソッドを使用することを決定しました。結果を投稿します。

3

データをGPUにロードするためにフレームごとの作業を行う必要のあるアプローチには、欠陥があります。

うまくいくはずのアプローチの概要は次のとおりです。

地形を(かなり大きい)チャンクに分割し、それらのチャンクを固定頂点バッファーにロードする必要があります(高さマップのビット深度は重要ではありません!)。これらの頂点バッファーは、レンダリングされるのを待つだけで、GPUメモリに配置されます。適切なチャンクサイズを試してみる必要がありますが、128x128から始めるのがよいでしょう。

4096x4096の地形の場合、一度にGPUに快適にロードできる範囲を少し超えています-おそらく数百MBの頂点データです(ただし、賢い)。そのため、バックグラウンドでGPUから頂点バッファーをロードおよびアンロードする必要がある場合があります。

(チャンクのバックグラウンドロードを実装する場合、これは非常にスケーラブルなはずです!)

後はあなたがGPUに頂点データを持っている、それは上の可視カリングを行うための適切な時間であるあたり、チャンク根拠は。カメラの背後にあることがわかっている場合は、チャンクをレンダリングするコマンドを送信する必要はありません。

CPUで三角形ごとのカリングを行うことはほとんどありません。

GPUは、画面に表示されていない三角形を、これまでよりもはるかに速くカリングします。

パフォーマンスの詳細については、ゲーム開発サイトでこの回答をご覧ください。


0

私は決してXNAの専門家ではないので、間違っている場合は修正してください。しかし、このような状況には組み込みの最適化が実際にあるという印象を受けました。レンダリング距離を設定できることは知っています。それ以降は何もレンダリングされません。あなたの場合は残りの地形になります。ただし、これはレンダリングされた世界にかなり魅力のないエッジを残すため、ほとんどのオープンワールドゲームにあるフォギングのようなものを実装する必要があります。


組み込みのソリューションがありますが、私が遭遇した問題は、1つの大きなプリミティブをレンダリングしようとしていて、プリミティブのポリゴンの制限を超えていたということです。したがって、描画せず、例外をスローするだけです。
sammarks
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.