大きな地形メッシュを効率的にレンダリングする方法は?


10

最近、ゲームに地形を生成する最良の方法について考えている問題に悩まされています。別のプロジェクトでは、通常はハイトマップを使用したため、すべてのコアワークは使用されたエンジンに基づいていましたが、地形には正確に描画する必要がある数百万の特定のポリゴンがあるため、これは実行できません。また、それらの多くはYベクトルから解析できません(ポリゴンが下に隠れているため)。つまり、ハイトマップはここでは役に立ちません。この場合、COLLADAオブジェクトを使用する必要がありました。

誰かがBlenderのようなソフトウェア内でモデルを手動で分割するように言ったが、残念なことに、これらの地形は別のソフトウェアのチャンクで作成され、ゲームに読み込まれるため、これも不可能である(それはアイデアだ)。したがって、これは毎回手動でスライスすることを余儀なくされる大きな仕事になるでしょう。

したがって、この問題を1週間解決して、このメッシュ、つまり地形をカメラのフラストラムに応じて手続き的にロードする方法について1週間研究してきました。これにより、可能な限りパフォーマンスを節約できます。手続き型メッシュの生成に関する多くのドキュメントに出くわしましたが、メッシュを八分木にマッピングすることで問題を解決できると思います。これは少なくとも私にとっては大きな仕事であり、それが私がここにいる理由です。なぜなら、私は経験豊富な人々から聞く前に間違った道をたどるリスクを冒したくないからです。

要するに、私には何百万もの頂点とインデックスがあり、それらが一緒になって地形を形成していますが、明らかな理由により、それらを同時に描画することはできません。何らかの手続きが必要です。大きなメッシュを地形として扱うために、それを行うための最良の方法は何ですか?それに関する具体的な本はありますか?それを実装する最良の方法はありますか?

どんな間違いでもすみません、私はこの分野の初心者です。

回答:


12

基本的なチャンクは、開始するための良い方法です。必要に応じて、後でoctreesなどのより高度なデータ構造に移動できます。とりあえず、モデルをディスクからロードするときに、地形を特定の次元のチャンクに分割するだけです。

データに応じて、地形を全高にまたがる平面上の柱に分割するか、空間内の立方体に分割することができます。コードは完全ではありません(fmod、ベクトルの初期化、インデックスなど)が、最初に使用できるはずです。

// Load vertices from disk
struct point { double x, y, z; };    
vector<point> vertices;

// Create container for chunks
typedef pair<int, int> key;
unordered_map<key, vector<point>> chunks;
const int chunksize = 10;

// For each vertex
for (int i = 0; i < vertices.size(); ++i) {
    // Fetch global coordinates
    int x = vertices[i].x,
        y = vertices[i].y,
        z = vertices[i].z;

    // Find containing chunk
    key k;
    k.first  = x / chunksize;
    k.second = z / chunksize;

    // Calculate local coordinates
    point p;
    p.x = x % chunksize;
    p.y = y;
    p.z = z % chunksize;

    // Add to chunk
    chunks[k].push_back(p);
}

// Create separate buffers for each chunk
// ...

これでメッシュを分割したので、LODおよびカリングテクニックを実行して、非表示のチャンクのレンダリングをスキップできます。

  • 視距離はあなたが始める場所です。たとえば、カメラのビュー距離など、特定の距離内のチャンクのみをレンダリングします。表示距離が小さいほど、描画する必要があるテレインのチャンクが少なくなるため、パフォーマンスが向上します。

  • 錐台カリングは、カメラの視野錐台と交差するメッシュのみをレンダリングする一般的な手法です。これにより、パフォーマンスが最大になる可能性が高くなります。

最適な結果を得るには、チャンクサイズと表示距離を試してください。チャンクサイズは、正確なカリングと簡単な計算の間のトレードオフです。さらに最適化するには、これらのより高度な最適化をご覧ください。

  • オクルージョンカリングは、非常に低い解像度でCPU上のメッシュをレンダリングすることで実行できます。これにより、他のメッシュの背後に隠れているメッシュを早期に検出できます。それらはGPUに送信する必要がないため、三角形を拒否する前に実行されるはずだった多くの頂点シェーダーの実行を保存できます。

  • 詳細レベルとは、チャンクの低解像度メッシュを計算することを意味します。カメラまでの距離に基づいて、描画するメッシュの1つを選択します。これにより、遠くのチャンクはそれほど詳細を必要としないため、頂点の数を減らすことができます。カメラから離れた領域の複数の立方体を1つの低解像度メッシュにマージできるため、このアプローチは八分木でうまく機能します。ただし、解像度が異なる2つのチャンク間のエッジをシームレスにマージすることは簡単ではありません。

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