algorithm - 如何正确使用SpriteBatch的变换矩阵?

标签 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) for DrawingMatrix

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

其次,在绘制实体之前,我调用 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);
    }

请澄清以上代码的更正。我需要的不是在原点缩放,而是在 ScaleCenterX 和 ScaleCenterY 处缩放,如何实现这一点?

添加:这是我的引擎绘制过程的示例:

  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. 调用 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. 例如,在我的 Rect 类中调用 Draw():

    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);
    }
    

如果我用 this.SpriteBatch.Begin() 替换上面的 Begin 代码,矩形就会正确绘制,所以我猜这是因为矩阵的原因。

最佳答案

第一个问题是一个简单的错误:SpriteBatch 的默认值为 CullCounterClockwise,但您指定了 CullClockwise 导致所有 Sprite 恢复- 脸部剔除。如果您只想使用默认渲染状态,则可以传递 null - 无需显式指定它们。

(如果您使用负比例,则需要更改剔除模式。)

要回答你的第二个问题:你需要翻译“向后”以将缩放原点(你的 ScaleCenterX 和 ScaleCenterY )放置在世界原点 (0,0) 。变换总是发生在 (0,0) 附近。所以通常的顺序是:将 Sprite 原点平移回世界原点,缩放,旋转,平移以将 Sprite 原点放置在所需的世界位置。

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

关于algorithm - 如何正确使用SpriteBatch的变换矩阵?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14229986/

相关文章:

python - 一个列表与另一个列表的排列组合

java - 如何将 MD5 哈希值转换为字符串?

algorithm - 包装 2D 柏林噪声

c - 对角带中的遍历矩阵

algorithm - 匈牙利算法将一组与自身匹配

arrays - 如何获取矩阵列中最后一个非零值的数组?

java - 可互换的键/值 HashMap Set 结构

c# - XNA动画 Sprite 从透明到不透明

c# - 在没有内容管道的情况下在 XNA 中加载模型

silverlight - 覆盖 Silverlight 的 Internet Explorer 事件