XNA Monogame有效绘制基元

时间:2016-07-22 06:01:01

标签: c# xna monogame

我是Monogame(OpenGL)的新手。

我想绘制10.000多个图元,只是矩形。

public class RectangleObject
{
    public BasicEffect Effect { get; set; }
    public Matrix PointTranslation { get; set; }
    public Matrix PointRotation { get; set; }
    public Matrix PointScale { get; set; }
    public VertexPositionColor[] VerticesList { get; set; }
    private VertexBuffer vertexBuffer;
    private Game game;

    public RectangleObject(Game game)
    {
        this.game = game;

        Effect = new BasicEffect(game.GraphicsDevice) { VertexColorEnabled = true };
        VerticesList = new VertexPositionColor[4];

        vertexBuffer = new VertexBuffer(game.GraphicsDevice, 
                                        typeof(VertexPositionColor), 
                                        VerticesList.Length, 
                                        BufferUsage.WriteOnly);

        vertexBuffer.SetData<VertexPositionColor>(VerticesList.ToArray());
        game.GraphicsDevice.SetVertexBuffer(vertexBuffer);
    }

    public void DrawRectangle()
    {
        Effect.World = PointScale * PointRotation * PointTranslation;
        Effect.CurrentTechnique.Passes[0].Apply();
        game.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(
                          PrimitiveType.TriangleStrip, 
                          VerticesList, 
                          0, 
                          vertexBuffer.VertexCount / 2);
    }
}

我想旋转/平移/缩放每个矩形对象,因为每个对象有3个矩阵。 应用程序正在加载内容,创建100 * 100的RectangleObjects网格,并在Draw()方法中调用RectangleObject的DrawRectangle()方法。 当我尝试绘制50 * 50时,它保持60FPS。但如果我尝试绘制10.000个矩形,应用程序运行15-25FPS。

附加的dotTrace日志: dotTrace log

问题是:

  • 这是绘制对象的有效方法吗?
  • 我可以提高申请表现吗?
  • 你能给我链接,我可以在哪里阅读有关表演的内容吗?

1 个答案:

答案 0 :(得分:2)

我怀疑你的游戏正在向GPU重新发送相同的几何体,无论几何体是否已经改变(从你所说的那些应该是静态的)。此外,我认为出于性能原因,您将受益于索引原语(见下文)。

根据Riemer,您应在致电SetVertexBuffer()之前致电DrawIndexedPrimitives()

  

完成后,您只需要使用 DrawIndexedPrimitives方法而不是DrawUserIndexedPrimitives 方法指示您的图形卡从其自己的内存中获取顶点和索引数据。在我们调用此方法之前,我们需要让您的显卡知道它应该从存储在自己内存中的缓冲区读取Tell me more...

e.g。 (来自Riemer)

 device.Indices = myIndexBuffer;  // <------------- NEW
 device.SetVertexBuffer(myVertexBuffer);
 device.DrawIndexedPrimitives(PrimitiveType.TriangleList,  //
                              0, 
                              0, 
                              vertices.Length, 
                              0, 
                              indices.Length / 3); 

请注意DrawIndexedPrimitives的使用。我建议你调查DrawUserPrimitives以上。另请注意,您需要更改代码才能使用索引。

请勿在{{1​​}}构造函数中调用game.GraphicsDevice.SetVertexBuffer(vertexBuffer)。我无法想到你应该在这些对象中进行任何GPU更改的原因。在RectangleObject()方法中执行此操作。

结论

通过这些更改,您将获得基本上VBO与当前的性能,GPU目前正在考虑的“动态”#34; VAO。

通过使用相同几何体的实例化而不是将相同的几何体乘以10,000次,可以获得出色的性能。

告诉我更多