2012-05-12 15 views
2

私はDrawUserIndexedPrimitivesを使って線からなるモデルを描画してXNAで3D WP7ゲームを作ろうとしています これはすべてうまくいきましたが、今はすべてのモデルに独自の回転を​​与えたいと思います。 現在、BasicEffectを使用してすべてのモデルを描画しています。私はその回転を設定することができますが、すべてのオブジェクトは同じ回転を持ちます。オブジェクトごとに異なる回転を設定する方法はありますか? 私は現在、私が使用できるソリューションのカップルを作ってみたが、私はそれらのいずれかに満足していないよ:XNA for WP7のゲーム:DrawUserIndexedPrimitives

  • 以上のループ、その後、独自の世界で、すべてのオブジェクトのための新しいBasicEffectを作成します。すべてのオブジェクトが基本的な効果を引き出し、描画します。これらのBasicEffectがすべてオーバーヘッドを生み出すと思います。モデルから効果を分離したいと思います。
  • 自分でポイントを計算します(つまり、回転を計算して、それらの値を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()オブジェクトの回転、平行移動、スケール、モデルとの行列を返します。 GetPoints()ポイントとmodel.Linesのリストは、接続されたポイントのインデックスを持つリストです

答えて

2

通常は、BasicEffectなどの任意のタイプのエフェクトが必要です。その理由は、エフェクトは2つの主なものから成っているからです:GPU用に書かれたコード(ライティングなど)とそれが公開するパラメータ(例えばEffect.World、世界の行列)。毎回同じようにGPUコードを2回以上コンパイルするという点はあまりありませんので、考慮する必要があるのはパラメータだけです。

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

2番目の箇条書きに答えるには、まったく正しいです。 GPUは大規模な並列性を持つポイントの変換を行うように作られているため、速度が遅くなるため、自分で試してみることはお勧めしません。

DrawUserIndexedPrimitivesについては、私はグラフィックスパイではありませんが、一般に、頂点が常に変化している状況(ソフトボディのブロブや布など)のために予約されています。基本的には、ただの翻訳、回転、および尺度によって。 GPUは、VertexBufferと呼ばれる特別なプリミティブを公開しています。その目的は、GPUメモリに多数のポイントを格納することです(本当に素早くアクセスできます)。そこを移動したい場合は、GPUはすべての点を変換します(ただし、渡す必要があるのは、翻訳、回転、縮尺、およびその良さです)。 DrawUserIndexedPrimitivesを使用すると、実際にGPUにすべての点をフレームごとに送信する必要があります。これは遅くなります。

幸運にも、グラフィックスカードは、実際には三角形を描くのではなく三角形の辺を線として描画する 'Wireframe'という特殊な描画モードを実装しています。あなたが呼び出す前に、ワイヤフレームモードを設定するには、描画次の操作を行います。今

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

を独自の回転を​​適用するという点で、あなたが実際に行うために必要なのは回転行列で世界行列を掛けている(Matrix.CreateRotationXのようなものを使用(yourAngle))。

0

あなたの現在のソリューションは、私はTHW世界がpass.Apply()の前に割り当てるだろうけれども、大丈夫です

あなたはいくつかのモデルを持っている場合は、トランスフォームでのシェーダや配列に渡し、そしてあなたの頂点に追加することができますこの配列のインデックスを構造化します。

この方法で、すべてのモデルを1回のパスで描画できます。

関連する問題