You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将SpriteBatch实现的公告板精灵改为Y轴对齐?

仅绕Y轴旋转的公告板SpriteBatch实现方案

原教程中的全向公告板会完全跟随相机视角旋转,导致相机俯仰时精灵平躺、与3D物体穿插的问题。要实现**仅绕Y轴旋转(圆柱公告板)**的效果,同时保留SpriteBatch的内置排序系统,可以通过修改视图矩阵来实现,无需自定义着色器。

关键思路

通过生成一个仅包含Y轴旋转分量的视图矩阵,移除原视图矩阵中的俯仰和滚转信息,让公告板始终保持垂直状态,只在水平方向朝向相机。

实现代码

首先添加一个生成圆柱公告板视图矩阵的辅助方法:

Matrix CreateCylindricalBillboardViewMatrix(Vector3 cameraPosition, Vector3 targetPosition, Vector3 up)
{
    // 提取相机到目标的水平方向(忽略Y轴分量)
    Vector3 lookDirection = targetPosition - cameraPosition;
    lookDirection.Y = 0; // 移除俯仰方向,只保留水平旋转
    if (lookDirection.LengthSquared() < float.Epsilon)
        lookDirection = Vector3.Forward; // 避免相机与目标同位置时出错
    lookDirection.Normalize();

    // 计算右向量与修正后的上向量
    Vector3 right = Vector3.Cross(up, lookDirection);
    right.Normalize();
    Vector3 newUp = Vector3.Cross(lookDirection, right);
    newUp.Normalize();

    // 构建仅包含Y轴旋转的视图矩阵
    return Matrix.CreateLookAt(cameraPosition, cameraPosition + lookDirection, newUp);
}

然后修改原教程中的代码,使用上述矩阵替代原视图矩阵:

Matrix invertY = Matrix.CreateScale(1, -1, 1);
// 替换为自定义的圆柱公告板视图矩阵
Matrix cylindricalView = CreateCylindricalBillboardViewMatrix(camera.Position, targetPosition, Vector3.Up);

basicEffect.World = invertY;
basicEffect.View = Matrix.Identity;
basicEffect.Projection = projection;

spriteBatch.Begin(SpriteSortMode.Deferred, null, null, DepthStencilState.DepthRead, RasterizerState.CullNone, basicEffect);

foreach (var billboardSprite in billboardSprites)
{
    Vector3 textPosition = new Vector3(0, 45, 0);

    // 使用修改后的视图矩阵计算空间位置
    Vector3 viewSpaceTextPosition = Vector3.Transform(textPosition, cylindricalView * invertY);

    const string message = "hello, world!";
    Vector2 textOrigin = spriteFont.MeasureString(message) / 2;
    const float textSize = 0.25f;

    spriteBatch.DrawString(spriteFont, message, new Vector2(viewSpaceTextPosition.X, viewSpaceTextPosition.Y), 
        Color.White, 0, textOrigin, textSize, SpriteEffects.None, viewSpaceTextPosition.Z);
}

spriteBatch.End();

效果说明

  • 公告板会始终保持垂直于XZ平面,仅绕Y轴旋转以朝向相机的水平方向,不会出现平躺或过度倾斜的情况。
  • 保留了SpriteBatch的单次Begin/End调用,因此可以继续使用它的内置排序系统(比如按Z轴深度排序),无需放弃SpriteBatch的便利特性。
  • 无需深入理解复杂矩阵运算,只需替换视图矩阵即可实现需求。

内容的提问来源于stack exchange,提问作者propellerhat23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 23:20:55