diff --git a/Cameras/Camera.cs b/Cameras/Camera.cs index 5462985..a4589a4 100644 --- a/Cameras/Camera.cs +++ b/Cameras/Camera.cs @@ -16,8 +16,15 @@ namespace Kav public float NearPlane { get; } public float FarPlane { get; } - public PerspectiveCamera(Vector3 position, Vector3 forward, Vector3 up, float fieldOfView, float aspectRatio, float nearPlane, float farPlane) - { + public PerspectiveCamera( + Vector3 position, + Vector3 forward, + Vector3 up, + float fieldOfView, + float aspectRatio, + float nearPlane, + float farPlane + ) { Position = position; Forward = forward; Up = up; @@ -26,7 +33,7 @@ namespace Kav FieldOfView = fieldOfView; AspectRatio = aspectRatio; NearPlane = nearPlane; - FarPlane = farPlane; + FarPlane = farPlane; Projection = Matrix.CreatePerspectiveFieldOfView(FieldOfView, AspectRatio, NearPlane, FarPlane); } } diff --git a/Enums/SpriteBillboardConstraint.cs b/Enums/SpriteBillboardConstraint.cs new file mode 100644 index 0000000..ef85d7c --- /dev/null +++ b/Enums/SpriteBillboardConstraint.cs @@ -0,0 +1,9 @@ +namespace Kav +{ + public enum SpriteBillboardConstraint + { + None, + Horizontal, + Full + } +} diff --git a/Geometry/Sprite.cs b/Geometry/Sprite.cs index 80b2641..c306b06 100644 --- a/Geometry/Sprite.cs +++ b/Geometry/Sprite.cs @@ -10,30 +10,48 @@ namespace Kav public Vector2 Origin { get; } public float Rotation { get; } public Vector2 Scale { get; } + public SpriteBillboardConstraint BillboardConstraint { get; } + + public Matrix TransformMatrix { get; } public Sprite( Texture2D texture, Vector3 position, Vector2 origin, float rotation, - Vector2 scale + Vector2 scale, + SpriteBillboardConstraint billboardConstraint = SpriteBillboardConstraint.None ) { Texture = texture; Position = position; Origin = origin; Rotation = rotation; Scale = scale; + BillboardConstraint = billboardConstraint; + TransformMatrix = ConstructTransformMatrix(Position, Scale); } public Sprite( Texture2D texture, - Vector3 position + Vector3 position, + SpriteBillboardConstraint billboardConstraint = SpriteBillboardConstraint.None ) { Texture = texture; Position = position; Origin = Vector2.Zero; - Rotation = 0f; + Rotation = 0; Scale = Vector2.One; + BillboardConstraint = billboardConstraint; + TransformMatrix = ConstructTransformMatrix(Position, Scale); + } + + private static Matrix ConstructTransformMatrix( + Vector3 position, + Vector2 scale + ) { + return + Matrix.CreateTranslation(position) * + Matrix.CreateScale(scale.X, scale.Y, 1); } } } diff --git a/Renderer.cs b/Renderer.cs index ff21b4b..047c386 100644 --- a/Renderer.cs +++ b/Renderer.cs @@ -254,35 +254,53 @@ namespace Kav DepthRender(camera, modelTransforms); GraphicsDevice.Clear(ClearOptions.Target, new Color(0, 0, 0, 0), 1f, 0); - Matrix invertY = Matrix.CreateScale(1, -1, 1); - - BasicEffect.World = invertY; - BasicEffect.View = Matrix.Identity; + BasicEffect.View = camera.View; BasicEffect.Projection = camera.Projection; BasicEffect.TextureEnabled = true; BasicEffect.VertexColorEnabled = true; - SpriteBatch.Begin(0, null, null, DepthStencilState.DepthRead, RasterizerState.CullNone, BasicEffect); - foreach (var sprite in sprites) { - // transform view space on CPU so we don't have to break the batch - Vector3 viewSpacePosition = Vector3.Transform(sprite.Position, camera.View * invertY); + if (sprite.BillboardConstraint == SpriteBillboardConstraint.None) + { + BasicEffect.World = sprite.TransformMatrix; + } + else if (sprite.BillboardConstraint == SpriteBillboardConstraint.Horizontal) + { + BasicEffect.World = Matrix.CreateConstrainedBillboard( + sprite.Position, + camera.Position, + Vector3.Up, + camera.Forward, + camera.Position - sprite.Position + ); + } + else + { + BasicEffect.World = Matrix.CreateConstrainedBillboard( + sprite.Position, + camera.Position, + Vector3.Up, + null, + null + ); + } + SpriteBatch.Begin(0, null, null, DepthStencilState.DepthRead, RasterizerState.CullNone, BasicEffect); SpriteBatch.Draw( sprite.Texture, - new Vector2(viewSpacePosition.X, viewSpacePosition.Y), + Vector2.Zero, null, Color.White, - 0, + sprite.Rotation, sprite.Origin, - sprite.Scale / new Vector2(sprite.Texture.Width, sprite.Texture.Height), + sprite.Scale / new Vector2(sprite.Texture.Width, -sprite.Texture.Height), 0, - viewSpacePosition.Z + 0 ); + SpriteBatch.End(); } - SpriteBatch.End(); GraphicsDevice.SetRenderTarget(renderTarget); GraphicsDevice.Clear(new Color(0, 0, 0, 0));