2

DrawUserIndexedPrimitives を使用して、線で構成されるモデルを描画することにより、XNA で 3D WP7 ゲームを作成しようとしています。現在、すべてのモデルを描画するために BasicEffect を使用しています。回転を設定できますが、すべてのオブジェクトが同じ回転になります。オブジェクトごとに異なる回転を設定する方法はありますか? 現在、使用できるいくつかのソリューションを考え出しましたが、どちらにも満足していません。

  • 独自の World を使用して、すべてのオブジェクトに新しい BasicEffect を作成し、すべてのオブジェクトをループして基本的な効果を取得して描画します。これらすべての BasicEffects は多くのオーバーヘッドを作成すると思います。モデル。
  • 自分でポイントの計算を行います (つまり、回転を計算し、それらの値を DrawUserIndexedPrimitives メソッドに渡します) - これは非常にコストのかかる計算であり、パフォーマンスを大幅に低下させます。

ここでおすすめのルートはありますか?

DrawUserIndexedPrimitives が使用するのに最適な方法であるかどうかはわかりません。線を描画して回転できるようにしたいだけです。これを行うためのより良い方法があれば、教えてください:)

私の現在の解決策:

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.Black);

    foreach (var model in _models)
    {

        foreach (var pass in model.Effect.CurrentTechnique.Passes)
        {
            pass.Apply();
            model.Effect.World = _model.GetWorld();

            var points = model.GetPoints();
            GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.LineList, points, 0, points.Length, model.Lines, 0, model.Lines.Length / 2);

            _models[0].Draw(GraphicsDevice);
        }
    }

    base.Draw(gameTime);
}

model.GetWorld() は、オブジェクトの回転、平行移動、およびスケールを含むマトリックスを返します。model.GetPoints() は、ポイントと model.Lines を含むリストです。接続されたポイントのインデックスを含むリストです。

4

2 に答える 2

2

通常は、任意の種類の効果 (BasicEffect など) のうちの 1 つだけが必要です。その理由は、エフェクトが 2 つの主なもので構成されているためです。GPU 用に記述されたコード (ライティングなど) と、GPU が公開するパラメーター (Effect.World、ワールド マトリックスなど) です。GPU コードは毎回同じになるため、複数回コンパイルする意味はあまりありません。そのため、他に考慮しなければならないのはパラメーターだけです。

pass.Apply() の呼び出しに注目してください。これが実際に行っていることは、描画する前に、エフェクトに設定したすべてのパラメーターを毎回 GPU にアップロードすることです。うまくいけば、個別に設定された回転で一連の効果を作成するのではなく、各描画の直前に単一の効果に回転を設定して Apply を呼び出すことができるはずです。さらに、Effect.World の設定は実際には pass.Apply() の前に来る必要があります。

2 番目の箇条書きに答えるには、完全に正しいです。GPU は大規模な並列処理でポイントの変換を行うように作られているため、遅くなるので自分で試してはいけません。

DrawUserIndexedPrimitives に関しては、私はグラフィックスマニアではありませんが、通常、その呼び出しは、頂点が絶えず変化する状況 (ソフト ボディのブロブやクロスなど) のために予約されています。回転、およびスケール。GPU は、VertexBuffer と呼ばれる特別なプリミティブを公開します。このプリミティブの全体的な目的は、多数のポイントを GPU メモリに格納することです (これにより、ポイントへのアクセスが非常に高速になります)。そこから移動したい場合は、GPU がすべてのポイントを変換します (ただし、渡す必要があるのは移動、回転、スケーリングだけであり、準備は整っていることに注意してください)。DrawUserIndexedPrimitives を使用すると、実際にはフレームごとにすべてのポイントを GPU に送信する必要があります。

運が良ければ、グラフィックス カードは実際には「ワイヤフレーム」と呼ばれる特別な描画モードを実装しています。これは、三角形を描画する代わりに、三角形のエッジを線として描画するだけです。ワイヤフレーム モードを設定するには、Draw を呼び出す前にこれを行います。

this.GraphicsDevice.RasterizerState.FillMode = FillMode.WireFrame;

独自の回転を​​適用するという点では、実際に行う必要があるのは、ワールド マトリックスに回転マトリックスを乗算することだけです (Matrix.CreateRotationX(yourAngle) などを使用します)。

于 2012-05-13T04:24:04.023 に答える
0

あなたの現在の解決策は問題ありませんが、pass.Apply() の前に世界の割り当てを行います

モデルがほとんどない場合は、変換を使用してシェーダーと配列に渡し、頂点構造にこの配列へのインデックスを追加できます。

このようにして、すべてのモデルを 1 回のパスで描画できます。

于 2012-05-13T04:26:36.987 に答える