【发布时间】:2013-01-25 16:46:21
【问题描述】:
我通常在 XNA/Monogame 中使用 SpriteBatch 进行 2d 游戏,并且最近刚刚深入研究了 DrawUserIndexedPrimatives 等 3D 绘图方法。我正在做一个项目,我们的动画师希望能够剪切精灵和纹理。
使用SpriteBatch,您可以在SpriteBatch 上传入一个矩阵,开始剪切一个对象。比如:
//translate object to origin
Matrix translate1 = Matrix.CreateTranslation(-rectangle.X, -rectangle.Y, 0);
//skew the sprite 33 degrees on the X and Y axis
Matrix skew = Matrix.Identity;
skew.M12 = (float)Math.Tan(33 * 0.0174532925f);
skew.M21 = (float)Math.Tan(33 * 0.0174532925f);
//translate object back
Matrix translate2 = Matrix.CreateTranslation(rectangle.X, rectangle.Y, 0);
Matrix transform = translate1 * skew * translate2;
_spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied,
SamplerState.PointWrap, DepthStencilState.Default,
RasterizerState.CullCounterClockwise, null, transform);
_spriteBatch.Draw(_texture, rectangle, Color.White);
_spriteBatch.End();
这个明显的缺点是它需要你为每个剪切的精灵创建一个新的SpriteBatch 开始和结束调用。我们目前只需要 2 次调用 SpriteBatch 在我们的游戏中开始。一个用于 UI,一个用于 World 的东西。我们的美工想要使用剪切来处理摇摆的树木或为生物的腿和四肢设置动画,所以如果我们给他们选择的话,我可以看到这个数字会跃升至 10 多个单独的批次。
平均水平有大约 250 个元素,每个元素包含 10-20 个精灵。
我为 Android 编写了一个测试,该测试调用了 1000 个精灵的绘制。在没有任何倾斜的情况下,它可以在大约 11 秒或大约 53fps 内绘制全部 1000、600 次。但如果我每十个精灵倾斜一次(添加 100 个新的SpriteBatch 调用),则需要 47 秒,或大约 12fps。
这真的很糟糕。即使只有 200 个精灵(每十分之一倾斜),测试也会下降到 28fps。
所以我还使用用DrawUserIndexedPrimitives 绘制的四边形创建了相同的测试。每个 Quad 使用在 Game 类中创建并通过 Sprite 类构造函数传入的共享 BasicEffect。我在每个pass.Apply() 之前设置了世界矩阵和纹理,如下所示:
if (_basicEffect != null)
{
foreach (EffectPass pass in _basicEffect.CurrentTechnique.Passes)
{
_basicEffect.World = Transform;
_basicEffect.Texture = _texture;
pass.Apply();
GraphicsDevice.DrawUserIndexedPrimitives
<VertexPositionNormalTexture>(
PrimitiveType.TriangleList,
_quad.Vertices, 0, 4,
_quad.Indices, 0, 2);
}
对于 1000 个精灵,没有倾斜,这给了我 12fps(我想这就像拨打 1000 次 spriteBatch 电话)。这真的很糟糕。但是对于每 10 个精灵倾斜的只有 200 个精灵,我得到 46fps,这明显优于 SpriteBatch(即使我调用了 200 次 DrawUserIndexedPrimitives)。
---我的问题---
我怎样才能将我的调用批处理到DrawUserIndexedPrimitives(或类似的东西),同时让我的精灵每个都包含在它们自己的继承DrawableGameComponent的类中?由于我们游戏引擎的性质以及它处理动画和碰撞等的方式,最后一部分非常重要。
我已经阅读了有关 Vertex Buffers 和 DrawIndexedPrimitives 的所有内容,但我的头并没有完全理解它,也不知道如何为在此绘制的精灵分配新的纹理和世界变换方式。
如果我批处理这些调用,我是否应该期待与 SpriteBatch 相似/更好的性能?
【问题讨论】:
标签: 3d xna drawing monogame spritebatch