如何将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
相关产品推荐
相关产品推荐

