tweak to mesh sprite draws

mesh_sprite_draw
cosmonaut 2020-12-10 00:34:06 -08:00
parent 7f0bf47f07
commit 8ff6e26887
3 changed files with 94 additions and 49 deletions

View File

@ -0,0 +1,24 @@
using Microsoft.Xna.Framework;
namespace Kav.Data
{
public struct MeshSpriteDrawData
{
public MeshSprite MeshSprite { get; }
public SpriteBillboardConstraint BillboardConstraint { get; }
public Matrix TransformMatrix { get; }
public UVOffsets UVOffsets { get; }
public MeshSpriteDrawData(
MeshSprite meshSprite,
SpriteBillboardConstraint billboardConstraint,
Matrix transformMatrix,
UVOffsets uVOffsets
) {
MeshSprite = meshSprite;
BillboardConstraint = billboardConstraint;
TransformMatrix = transformMatrix;
UVOffsets = uVOffsets;
}
}
}

22
Data/UVOffsets.cs Normal file
View File

@ -0,0 +1,22 @@
using Microsoft.Xna.Framework;
namespace Kav.Data
{
public struct UVOffsets
{
public static UVOffsets Default { get; } = new UVOffsets(
new Vector2(0, 0), new Vector2(1, 1)
);
// (start / width), (end / width)
public Vector2 StartUV { get; }
// (start / height), (end / height)
public Vector2 EndUV { get; }
public UVOffsets(Vector2 startUV, Vector2 endUV)
{
StartUV = startUV;
EndUV = endUV;
}
}
}

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using Kav.Data;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
@ -117,7 +118,7 @@ namespace Kav
public void MeshSpriteRender( public void MeshSpriteRender(
RenderTarget2D renderTarget, RenderTarget2D renderTarget,
PerspectiveCamera camera, PerspectiveCamera camera,
IEnumerable<(MeshSprite, SpriteBillboardConstraint, Matrix)> meshSpriteBillboardTransforms, IEnumerable<MeshSpriteDrawData> meshSpriteDrawDatas,
AmbientLight ambientLight, AmbientLight ambientLight,
IEnumerable<PointLight> pointLights, IEnumerable<PointLight> pointLights,
DirectionalLight? directionalLight DirectionalLight? directionalLight
@ -158,17 +159,24 @@ namespace Kav
var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection); var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
foreach (var (sprite, transform) in FrustumCull(boundingFrustum, BillboardTransforms(camera, meshSpriteBillboardTransforms))) foreach (var data in meshSpriteDrawDatas)
{ {
DiffuseLitSpriteEffect.NormalMapEnabled = sprite.Normal != null; var matrix = BillboardTransforms(camera, data.TransformMatrix, data.BillboardConstraint);
DiffuseLitSpriteEffect.World = transform; if (FrustumCull(boundingFrustum, data.MeshSprite, matrix))
{
continue;
}
GraphicsDevice.Textures[0] = sprite.Texture; DiffuseLitSpriteEffect.NormalMapEnabled = data.MeshSprite.Normal != null;
GraphicsDevice.Textures[1] = sprite.Normal;
GraphicsDevice.SetVertexBuffer(sprite.VertexBuffer); DiffuseLitSpriteEffect.World = matrix;
GraphicsDevice.Indices = sprite.IndexBuffer;
GraphicsDevice.Textures[0] = data.MeshSprite.Texture;
GraphicsDevice.Textures[1] = data.MeshSprite.Normal;
GraphicsDevice.SetVertexBuffer(data.MeshSprite.VertexBuffer);
GraphicsDevice.Indices = data.MeshSprite.IndexBuffer;
foreach (var pass in DiffuseLitSpriteEffect.CurrentTechnique.Passes) foreach (var pass in DiffuseLitSpriteEffect.CurrentTechnique.Passes)
{ {
@ -178,7 +186,7 @@ namespace Kav
PrimitiveType.TriangleList, PrimitiveType.TriangleList,
0, 0,
0, 0,
sprite.VertexBuffer.VertexCount, data.MeshSprite.VertexBuffer.VertexCount,
0, 0,
2 2
); );
@ -186,36 +194,34 @@ namespace Kav
} }
} }
private static IEnumerable<(MeshSprite, Matrix)> BillboardTransforms( private static Matrix BillboardTransforms(
PerspectiveCamera camera, PerspectiveCamera camera,
IEnumerable<(MeshSprite, SpriteBillboardConstraint, Matrix)> meshSpriteBillboardTransforms Matrix transform,
SpriteBillboardConstraint billboardConstraint
) { ) {
foreach (var (sprite, billboardConstraint, transform) in meshSpriteBillboardTransforms) if (billboardConstraint == SpriteBillboardConstraint.None)
{ {
if (billboardConstraint == SpriteBillboardConstraint.None) return transform;
{ }
yield return (sprite, transform); else if (billboardConstraint == SpriteBillboardConstraint.Horizontal)
} {
else if (billboardConstraint == SpriteBillboardConstraint.Horizontal) return Matrix.CreateConstrainedBillboard(
{ transform.Translation,
yield return (sprite, Matrix.CreateConstrainedBillboard( camera.Position,
transform.Translation, Vector3.Up,
camera.Position, camera.Forward,
Vector3.Up, camera.Position - transform.Translation
camera.Forward, );
camera.Position - transform.Translation }
)); else
} {
else return Matrix.CreateConstrainedBillboard(
{ transform.Translation,
yield return (sprite, Matrix.CreateConstrainedBillboard( camera.Position,
transform.Translation, Vector3.Up,
camera.Position, null,
Vector3.Up, null
null, );
null
));
}
} }
} }
@ -924,21 +930,14 @@ namespace Kav
} }
} }
private static IEnumerable<Matrix> FrustumCull<T>( private static bool FrustumCull<T>(
BoundingFrustum boundingFrustum, BoundingFrustum boundingFrustum,
T cullable, T cullable,
IEnumerable<Matrix> transforms Matrix transform
) where T : ICullable ) where T : ICullable {
{ var boundingBox = TransformedBoundingBox(cullable.BoundingBox, transform);
foreach (var transform in transforms) var containment = boundingFrustum.Contains(boundingBox);
{ return (containment == ContainmentType.Disjoint);
var boundingBox = TransformedBoundingBox(cullable.BoundingBox, transform);
var containment = boundingFrustum.Contains(boundingBox);
if (containment != ContainmentType.Disjoint)
{
yield return transform;
}
}
} }
private static BoundingBox TransformedBoundingBox(BoundingBox boundingBox, Matrix matrix) private static BoundingBox TransformedBoundingBox(BoundingBox boundingBox, Matrix matrix)