如何正确使用SpriteBatch的Transformation Matrix?

时间:2013-01-09 07:07:20

标签: algorithm matrix xna 2d transformation

我是XNA的新手,想在它上面开发一个轻量级的2D引擎,将实体组织成父子层次结构。在绘制孩子时我会想到矩阵,因为它们的位置,旋转和比例都取决于他们的父母。

如果我使用SpriteBatch.Begin(),我的矩形可以在屏幕上绘制,但是当我将它们更改为:

        this.DrawingMatrix = Matrix.Identity;
        this.SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.None, RasterizerState.CullClockwise, null, this.DrawingMatrix);

不再有任何东西了。我甚至为new Matrix()尝试了Matrix.CreateTranslation(0, 0, 0)DrawingMatrix

我的第一个问题是:为什么它不起作用?我不使用任何相机或视口。

其次,在绘制实体之前,我调用PreDraw来转换矩阵(我将在PostDraw处重置为原始状态):

    protected virtual void PreDraw(Engine pEngine)
    {
        pEngine.DrawingMatrix *=
            Matrix.CreateTranslation(this.X, this.Y, 0) *
            Matrix.CreateScale(this.ScaleX, this.ScaleY, 1) *
            Matrix.CreateRotationZ(this.Rotation);
    }

请澄清上述代码的更正。我需要缩放不是原点,但在ScaleCenterXScaleCenterY,我怎么能实现这个目标呢?

已添加:以下是我的引擎绘制过程的示例:

  1. 请拨打以下代码:

        this.DrawingMatrix = Matrix.CreateTranslation(0, 0, 0);
        this.SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.None, RasterizerState.CullClockwise, null, this.DrawingMatrix);
    
  2. 使用is:

    调用PreDraw()
    protected virtual void PreDraw(Engine pEngine)
    {
        pEngine.DrawingMatrix *=
            Matrix.CreateTranslation(this.X, this.Y, 0) *
            Matrix.CreateScale(this.ScaleX, this.ScaleY, 1) *
            Matrix.CreateRotationZ(this.Rotation);
    }
    
  3. 例如,在我的Draw()课程中调用Rect

    protected override void Draw(Engine pEngine)
    {
        pEngine.SpriteBatch.Draw(pEngine.RectangleTexture, new Rectangle(0, 0, (int)this.Width, (int)this.Height), new Rectangle(0, 0, 1, 1), this.Color);
    }
    
  4. 如果我将上述Begin代码替换为this.SpriteBatch.Begin(),则会正确绘制矩形,因此我猜这是因为矩阵。

1 个答案:

答案 0 :(得分:4)

第一个问题是一个简单的错误:SpriteBatch的默认值为CullCounterClockwise,但您已指定CullClockwise导致所有精灵被剔除。如果您只想使用默认渲染状态,则可以传递null - 您无需明确指定它们。

(如果使用负刻度,则需要更改剔除模式。)

要回答您的第二个问题:您需要翻译“返回”以将缩放原点(您的ScaleCenterXScaleCenterY)放置在世界原点(0,0)。转换总是发生在(0,0)附近。通常顺序是:将精灵原点转换回世界原点,缩放,旋转,平移以将精灵原点放置在所需的世界位置。

另外,我希望你的PostDraw没有应用反向转换(你让它听起来像它一样)。这很可能会导致精确度问题。您应该保存并恢复矩阵。