XNA for WP7游戏:DrawUserIndexedPrimitives

时间:2012-05-12 20:13:26

标签: c# windows-phone-7 3d xna

我正在尝试使用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()一个带有points和model的列表.Lines是一个带有连接点索引的列表

2 个答案:

答案 0 :(得分:2)

您通常只需要任何类型的效果之一(例如BasicEffect)。原因是因为效果包含两个主要内容:为GPU(照明等)编写的代码及其公开的参数(例如Effect.World,世界矩阵)。编译GPU代码的次数不会太多,因为每次都是相同的,所以我们唯一需要考虑的是参数。

注意调用pass.Apply()。实际上做的是每次在绘制之前将您在效果上设置的所有参数上传到GPU。有希望告诉你的是,你应该能够在每次绘制之前在单个效果上设置旋转并调用Apply,而不是创建一组具有单独设置旋转的效果。而且,设置Effect.World实际上应该在pass.Apply()。

之前

要回答第二个要点,你完全正确。 GPU可以在具有大量并行性的点上进行转换,因此最好不要自己尝试,因为它会很慢。

对于DrawUserIndexedPrimitives,我不是图形buff,但一般来说,这个调用是为你的顶点不断变化的情况保留的(比如软体blob或布料),基本上你没有办法用它来描述网格只是翻译,旋转和尺度。 GPU暴露了称为VertexBuffer的特殊基元,其整个目标是在GPU内存中存储一​​堆点(这使得它们非常快速地访问)。从那里,如果你想移动它,GPU将转换每一点(但请注意,你需要传递它的所有内容是平移,旋转和缩放以及它的好处)。使用DrawUserIndexedPrimitives实际上必须每帧都将所有点发送到GPU,这比较慢(多少,谁知道这些天没有测试)。

幸运的是,显卡实际上实现了一种称为“线框”的特殊绘图模式,而不是绘制三角形,只是将三角形的边缘绘制为线条。要设置线框模式,请在调用Draw:

之前执行此操作
this.GraphicsDevice.RasterizerState.FillMode = FillMode.WireFrame;

现在,在应用自己的旋转方面,您实际需要做的就是将世界矩阵乘以旋转矩阵(使用类似Matrix.CreateRotationX(yourAngle)的东西)。

答案 1 :(得分:0)

你当前的解决方案很好,但我会在pass.Apply()

之前做世界分配

如果您的模型很少,可以使用变换传递到着色器和数组,并将顶点结构添加到此数组的索引。

通过这种方式,您可以一次性绘制所有模型。

相关问题