Frustum Culling #4

Merged
cosmonaut merged 2 commits from frustum_culling into main 2020-10-20 19:21:00 +00:00
5 changed files with 73 additions and 5 deletions

View File

@ -1,12 +1,23 @@
using Microsoft.Xna.Framework;
namespace Kav namespace Kav
{ {
public class Mesh public class Mesh
{ {
public MeshPart[] MeshParts { get; } public MeshPart[] MeshParts { get; }
public BoundingBox BoundingBox { get; }
public Mesh(MeshPart[] meshParts) public Mesh(MeshPart[] meshParts)
{ {
MeshParts = meshParts; MeshParts = meshParts;
BoundingBox boundingBox = new BoundingBox();
foreach (var meshPart in MeshParts)
{
boundingBox = BoundingBox.CreateMerged(boundingBox, meshPart.BoundingBox);
}
BoundingBox = boundingBox;
} }
} }
} }

View File

@ -10,6 +10,8 @@ namespace Kav
public Triangle[] Triangles { get; } public Triangle[] Triangles { get; }
public Vector3[] Positions { get; } public Vector3[] Positions { get; }
public BoundingBox BoundingBox { get; }
private Texture2D albedoTexture = null; private Texture2D albedoTexture = null;
private Texture2D normalTexture = null; private Texture2D normalTexture = null;
private Texture2D metallicRoughnessTexture = null; private Texture2D metallicRoughnessTexture = null;
@ -50,6 +52,8 @@ namespace Kav
IndexBuffer = indexBuffer; IndexBuffer = indexBuffer;
Positions = positions; Positions = positions;
Triangles = triangles; Triangles = triangles;
BoundingBox = BoundingBox.CreateFromPoints(Positions);
} }
} }
} }

View File

@ -5,6 +5,7 @@ namespace Kav
public class Model public class Model
{ {
public Mesh[] Meshes { get; } public Mesh[] Meshes { get; }
public BoundingBox BoundingBox { get; }
public Color Albedo public Color Albedo
{ {
@ -51,6 +52,14 @@ namespace Kav
public Model(Mesh[] meshes) public Model(Mesh[] meshes)
{ {
Meshes = meshes; Meshes = meshes;
BoundingBox boundingBox = new BoundingBox();
foreach (var mesh in Meshes)
{
boundingBox = BoundingBox.CreateMerged(boundingBox, mesh.BoundingBox);
}
BoundingBox = boundingBox;
} }
public void DisableAlbedoMaps() public void DisableAlbedoMaps()

View File

@ -14,7 +14,7 @@ Essential
- [x] Cascading shadow maps - [x] Cascading shadow maps
- [x] Tone map shader - [x] Tone map shader
- [x] Poisson soft shadowing - [x] Poisson soft shadowing
- [ ] Frustum culling - [x] Frustum culling
- [x] Shadow-casting point lights - [x] Shadow-casting point lights
- [ ] Parabolic lights - [ ] Parabolic lights
- [x] Skyboxes - [x] Skyboxes

View File

@ -240,7 +240,9 @@ namespace Kav
PerspectiveCamera camera, PerspectiveCamera camera,
IEnumerable<(Model, Matrix)> modelTransforms IEnumerable<(Model, Matrix)> modelTransforms
) { ) {
foreach (var (model, transform) in modelTransforms) var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
foreach (var (model, transform) in FrustumCull(boundingFrustum, modelTransforms))
{ {
foreach (var modelMesh in model.Meshes) foreach (var modelMesh in model.Meshes)
{ {
@ -312,7 +314,9 @@ namespace Kav
GraphicsDevice.DepthStencilState = DepthStencilState.Default; GraphicsDevice.DepthStencilState = DepthStencilState.Default;
GraphicsDevice.BlendState = BlendState.Opaque; GraphicsDevice.BlendState = BlendState.Opaque;
foreach (var (model, transform) in modelTransforms) var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
foreach (var (model, transform) in FrustumCull(boundingFrustum, modelTransforms))
{ {
foreach (var modelMesh in model.Meshes) foreach (var modelMesh in model.Meshes)
{ {
@ -581,7 +585,9 @@ namespace Kav
effect.LightSpaceMatrixFour = lightSpaceMatrix; effect.LightSpaceMatrixFour = lightSpaceMatrix;
} }
foreach (var (model, transform) in modelTransforms) var boundingFrustum = new BoundingFrustum(lightSpaceMatrix);
foreach (var (model, transform) in FrustumCull(boundingFrustum, modelTransforms))
{ {
foreach (var modelMesh in model.Meshes) foreach (var modelMesh in model.Meshes)
{ {
@ -677,7 +683,9 @@ namespace Kav
targetUpDirection targetUpDirection
); );
foreach (var (model, transform) in modelTransforms) var boundingFrustum = new BoundingFrustum(LinearDepthEffect.View * LinearDepthEffect.Projection);
foreach (var (model, transform) in FrustumCull(boundingFrustum, modelTransforms))
{ {
foreach (var modelMesh in model.Meshes) foreach (var modelMesh in model.Meshes)
{ {
@ -706,5 +714,41 @@ namespace Kav
} }
} }
} }
private static IEnumerable<(Model, Matrix)> FrustumCull(
BoundingFrustum boundingFrustum,
IEnumerable<(Model, Matrix)> modelTransforms
) {
foreach (var modelTransform in modelTransforms)
{
var boundingBox = TransformedBoundingBox(modelTransform.Item1.BoundingBox, modelTransform.Item2);
var containment = boundingFrustum.Contains(boundingBox);
if (containment != ContainmentType.Disjoint)
{
yield return modelTransform;
}
}
}
private static BoundingBox TransformedBoundingBox(BoundingBox boundingBox, Matrix matrix)
{
var center = (boundingBox.Min + boundingBox.Max) / 2f;
var extent = (boundingBox.Max - boundingBox.Min) / 2f;
var newCenter = Vector3.Transform(center, matrix);
var newExtent = Vector3.TransformNormal(extent, AbsoluteMatrix(matrix));
return new BoundingBox(newCenter - newExtent, newCenter + newExtent);
}
private static Matrix AbsoluteMatrix(Matrix matrix)
{
return new Matrix(
Math.Abs(matrix.M11), Math.Abs(matrix.M12), Math.Abs(matrix.M13), Math.Abs(matrix.M14),
Math.Abs(matrix.M21), Math.Abs(matrix.M22), Math.Abs(matrix.M23), Math.Abs(matrix.M24),
Math.Abs(matrix.M31), Math.Abs(matrix.M32), Math.Abs(matrix.M33), Math.Abs(matrix.M34),
Math.Abs(matrix.M41), Math.Abs(matrix.M42), Math.Abs(matrix.M43), Math.Abs(matrix.M44)
);
}
} }
} }