3

多くの開発者がおそらく解決策を見つけたという問題に直面しています。小さな立方体 (100X100) で設計された床を持つ小さなプロジェクトがあります。この制限を超えると、ゲームが大幅に遅くなり、ラグが発生します。

床を描く方法は次のとおりです。

//Function to draw my ground ( 100 X 100 X 1)
    public void DrawGround(GameTime gameTime)
    {
        // Copy any parent transforms.
        Matrix[] transforms = new Matrix[this.model.Bones.Count];
        this.model.CopyAbsoluteBoneTransformsTo(transforms);

        //loop 1 cube high
        for (int a = 0; a < 1; a++)
        {
            //loop 100 along cube
            for (int b = 0; b < 100; b++)
            {
                //loop 100 cubic wide
                for (int c = 0; c < 100; c++)
                {
                    // Draw the model. A model can have multiple meshes, so loop.
                    foreach (ModelMesh mesh in this.model.Meshes)
                    {
                        // This is where the mesh orientation is set, as well 
                        // as our camera and projection.
                        foreach (BasicEffect effect in mesh.Effects)
                        {
                            effect.EnableDefaultLighting();
                            effect.World = transforms[mesh.ParentBone.Index] * Matrix.CreateTranslation(this.position);
                            effect.View = this.view;
                            effect.Projection = this.projection;


                        }

                        // Draw the mesh, using the effects set above.
                        mesh.Draw();
                    }
                }
            }
        }
    }

[VertexBuffer]「グラフィックスカードのメモリ」を利用した方が良いと思いますが、やりたいチュートリアルが見当たりません…

関数 "DrawGround" で [VertexBuffer] を使用する例を教えてください。 ここに画像の説明を入力 どうもありがとうございました!

4

1 に答える 1

7

tl;dr;

キューブの描画にはハードウェア インスタンス化を使用します。オプションで、視錐台カリングを使用して、非表示のインスタンスを描画しないようにします。Riemer のチュートリアルを読んで、頂点バッファーとインデックス バッファーを使い始めてください。


インスタンス化

アイデアは、頂点とインデックス バッファーがデバイスに 1 回バインドされ、 1回の描画呼び出しで複数回描画されるというものです。インスタンスは、モデルのインスタンスに固有の情報のみを含むデータの小さなパッケージです。このインスタンス データは、追加の頂点バッファーに書き込まれ、実際の頂点とインデックスを含むバッファーと共にデ​​バイスにバインドされます。

それをどのように活用できますか?

あなたの場合、次の設定があります。

  • キューブ メッシュ インデックスを含む IndexBuffer
  • 立方体メッシュの頂点を含む VertexBuffer
  • 描画するすべての立方体の変換を含む 2 番目の VertexBuffer
  • インスタンスデータを考慮した特別な入力レイアウト

キューブの位置が異なるだけなので、完全な変換マトリックスをシェーダーに送信する必要さえありません。インスタンスの位置を送信して、頂点の位置に追加するだけです。各インスタンスの色など、他のデータを送信することもできます。

どのように実装しますか?

簡単な Google 検索で、xna instancingの結果が大量に得られたので、それで始められるはずです。ここでは、有望と思われる 2 つのランダムな結果を示します。


フラスタムカリング

いつでも、シーン内のメッシュの一部だけが実際に表示される場合があります。オブジェクトが別のオブジェクトによって遮られているか、プレーヤーの視野から完全に外れている可能性があります。これらの目に見えないメッシュを描画する前に削除するプロセスは、カリングと呼ばれます。View Frustum Culling は 2 番目のケースに対応します。

カメラのボリュームと交差しないすべてのボリュームは非表示になります。

カメラの音量は?正投影には、ボックスの形のバウンディング ボリュームがあります。透視投影では、このボックスは先細りのピラミッドであり、近距離平面と遠距離平面によってトリミングされます。したがって、錐台を表示します。

それをどのように活用できますか?

錐台を使用して、現在のフレームで見えないインスタンスを識別します。カメラの視錐台と交差する立方体のみを描画します。プレイヤーが空を見ている場合、レンダリングの負荷が最大 100% 軽減される可能性があります。;-)

これを空間階層 ( quadtreeまたはoctree ) と組み合わせて、箱錐台交差計算の量を減らすことができます。

どのように実装しますか?

Xna はBoundingBox StructureBoundingFrustum Classを提供します。あなたがしなければならないのは、それらを使用することだけです。


ちょっとした欠点

View Frustum CullingHardware Instancingを組み合わせるのは難しい場合があります。インスタンスをカリングするということは、それらをインスタンス バッファからも削除する必要があることを意味します => つまり、全体を再作成することを意味します。立方体の可視性を計算し、数フレームごとに、またはカメラが急速に移動したときにのみインスタンス バッファを更新することを検討してください。これらの手法を最終的に実装する方法と範囲は、ユーザー次第であり、要件によって異なります。


頂点バッファーがどのように機能するかを知りたいと思っていることに気付きました。

頂点バッファー

画面に三角形を描画する前に、グラフィック デバイスを準備する必要があります。これには、シェーダー、サンプラー、テクスチャのバインド、およびもちろんジオメトリ データのバインドが含まれます。描画呼び出しが行われると、グラフィックス デバイスはシェーダーを実行し、出力をレンダー ターゲットに書き込みます。

現在、XNA の組み込みの抽象化を使用しています。これにより、プロセスが簡素化されます (そして、すべての制御がユーザーから奪われます)。シェーダー、定数、入力レイアウトなどのバインドは現在、すべて Effect クラスに隠され、Mesh クラスがジオメトリ面を処理します。

「mesh.Draw()」は何をしますか?

メッシュを作成すると、VertexBufferIndexBufferの 2 つのバッファーが作成されます。このバッファの作成にはコストがかかるため、これを 1 回だけ行うのは良いことです。描画メソッドを呼び出すと、バッファーがデバイスにバインドされ、描画呼び出しが行われます。コードで正しくコメントしたように、効果の状態を最初に設定する必要があります。

ただし、独自の頂点バッファーとインデックス バッファーを作成することもできます。

// Instantiate the VertexBuffer
var vertexBuffer = new VertexBuffer(
    device, 
    VertexPositionColorNormal.VertexDeclaration, 
    vertices.Length, 
    BufferUsage.WriteOnly
);

// Write data to the buffer
vertexBuffer.SetData(vertices);

// Instantiate the IndexBuffer
var indexBuffer = new IndexBuffer(
    device, 
    typeof(int), 
    indices.Length,      
    BufferUsage.WriteOnly
);

// Write data to the buffer
indexBuffer.SetData(indices);

...そしてそれらを手動でデバイスにバインドします:

device.Indices = myIndexBuffer;
device.SetVertexBuffer(myVertexBuffer);

このコードは、Riemer の XNA チュートリアルから直接取得したものです。

このサイトをチェックしてください。最初にグラフィックス プログラミングを始めたとき、このサイトは本当に役に立ちました。

于 2013-01-21T13:07:55.133 に答える