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/

相关文章:

performance - 前 10000 个质数的最有效代码?

algorithm - 这个分布式数据库数据位置优化算法的名称?

opengl - 投影矩阵如何工作?

c++ - OpenCV C++ 中的矩阵复共轭

c# - 如何从文件路径而不是内容加载 XNA 模型(例如 Model.FromStream 但它不存在)

string - 加速计算字母表中没有长度 > 1 的重复子串的字符串数

c++ - 我可以在每行中有一个包含不同列数的数组吗?

matlab - 在 MATLAB 中构建一个包含向量分量的巨大矩阵

c# - 使用 as 运算符进行转换,即使在使用 is 运算符验证 C# 中的类类型之后?

silverlight - Windows Phone 7 入门