Implement frustrum culling (gfx optimization)

This commit is contained in:
Drew DeVault 2015-05-15 15:48:20 -06:00
parent 1a95fee592
commit 5644827247
3 changed files with 47 additions and 42 deletions

View File

@ -109,6 +109,10 @@ namespace TrueCraft.Client.Linux
var drawableCoordinates = new HashSet<Coordinates3D>();
var boundingBox = new Microsoft.Xna.Framework.BoundingBox(
new Vector3(chunk.X * Chunk.Width, 0, chunk.Z * Chunk.Depth),
new Vector3(chunk.X * Chunk.Width + Chunk.Width, Chunk.Height, chunk.Z * Chunk.Depth + Chunk.Depth));
for (byte x = 0; x < Chunk.Width; x++)
{
for (byte z = 0; z < Chunk.Depth; z++)
@ -169,41 +173,12 @@ namespace TrueCraft.Client.Linux
transparentIndicies.AddRange(i);
}
}
return new Tuple<Mesh, Mesh>(
new Mesh(Graphics, opaqueVerticies.ToArray(), opaqueIndicies.ToArray()),
new Mesh(Graphics, transparentVerticies.ToArray(), transparentIndicies.ToArray()));
var meshes = new Tuple<Mesh, Mesh>(
new Mesh(Graphics, opaqueVerticies.ToArray(), opaqueIndicies.ToArray(), false),
new Mesh(Graphics, transparentVerticies.ToArray(), transparentIndicies.ToArray(), false));
meshes.Item1.BoundingBox = boundingBox;
meshes.Item2.BoundingBox = boundingBox;
return meshes;
}
}
}
/*
if (id != 0)
{
var descriptor = new BlockDescriptor
{
ID = id,
Metadata = chunk.GetMetadata(coords),
BlockLight = chunk.GetBlockLight(coords),
SkyLight = chunk.GetSkyLight(coords),
Coordinates = coords
};
var provider = BlockRepository.GetBlockProvider(id);
if (provider.RenderOpaque)
{
int[] i;
var v = BlockRenderer.RenderBlock(provider, descriptor,
new Vector3(chunk.X * Chunk.Width + x, y, chunk.Z * Chunk.Depth + z),
opaqueVerticies.Count, out i);
opaqueVerticies.AddRange(v);
opaqueIndicies.AddRange(i);
}
else
{
int[] i;
var v = BlockRenderer.RenderBlock(provider, descriptor,
new Vector3(chunk.X * Chunk.Width + x, y, chunk.Z * Chunk.Depth + z),
transparentVerticies.Count, out i);
transparentVerticies.AddRange(v);
transparentIndicies.AddRange(i);
}
}
*/
}

View File

@ -1,6 +1,7 @@
using System;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using System.Linq;
namespace TrueCraft.Client.Linux.Rendering
{
@ -10,8 +11,9 @@ namespace TrueCraft.Client.Linux.Rendering
public object Data { get; set; }
public VertexBuffer Verticies { get; set; }
public IndexBuffer Indicies { get; set; }
public BoundingBox BoundingBox { get; set; }
public Mesh(GraphicsDevice device, VertexPositionNormalTexture[] verticies, int[] indicies)
public Mesh(GraphicsDevice device, VertexPositionNormalTexture[] verticies, int[] indicies, bool calculateBounds = true)
{
Empty = verticies.Length == 0 || indicies.Length == 0;
if (!Empty)
@ -21,6 +23,12 @@ namespace TrueCraft.Client.Linux.Rendering
Verticies.SetData(verticies);
Indicies = new IndexBuffer(device, typeof(int), indicies.Length, BufferUsage.WriteOnly);
Indicies.SetData(indicies);
if (calculateBounds)
{
BoundingBox = new BoundingBox(
verticies.Select(v => v.Position).OrderBy(v => v.Length()).First(),
verticies.Select(v => v.Position).OrderByDescending(v => v.Length()).First());
}
}
}

View File

@ -28,6 +28,7 @@ namespace TrueCraft.Client.Linux
private readonly object ChunkMeshesLock = new object();
private Matrix Camera;
private Matrix Perspective;
private BoundingFrustum CameraView;
private BasicEffect OpaqueEffect, TransparentEffect;
@ -99,6 +100,10 @@ namespace TrueCraft.Client.Linux
OpaqueEffect.DirectionalLight2.SpecularColor = Color.Black.ToVector3();
OpaqueEffect.TextureEnabled = true;
OpaqueEffect.Texture = Texture2D.FromStream(GraphicsDevice, File.OpenRead("Content/terrain.png"));
OpaqueEffect.FogEnabled = true;
OpaqueEffect.FogStart = 512f;
OpaqueEffect.FogEnd = 1000f;
OpaqueEffect.FogColor = Color.CornflowerBlue.ToVector3();
TransparentEffect = new BasicEffect(GraphicsDevice);
TransparentEffect.TextureEnabled = true;
@ -180,7 +185,9 @@ namespace TrueCraft.Client.Linux
player, player + lookAt,
Microsoft.Xna.Framework.Vector3.Up);
Perspective = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(70f), GraphicsDevice.Viewport.AspectRatio, 0.3f, 10000f);
Perspective = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(70f), GraphicsDevice.Viewport.AspectRatio, 0.01f, 1000f);
CameraView = new BoundingFrustum(Camera * Perspective);
}
protected override void Draw(GameTime gameTime)
@ -193,14 +200,29 @@ namespace TrueCraft.Client.Linux
OpaqueEffect.View = TransparentEffect.View = Camera;
OpaqueEffect.Projection = TransparentEffect.Projection = Perspective;
OpaqueEffect.World = TransparentEffect.World = Matrix.Identity;
int verticies = 0, chunks = 0;
lock (ChunkMeshesLock)
{
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
foreach (var chunk in ChunkMeshes)
chunk.Draw(OpaqueEffect);
{
if (CameraView.Intersects(chunk.BoundingBox))
{
verticies += chunk.Verticies.VertexCount;
chunks++;
chunk.Draw(OpaqueEffect);
}
}
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
foreach (var chunk in TransparentChunkMeshes)
chunk.Draw(TransparentEffect);
{
if (CameraView.Intersects(chunk.BoundingBox))
{
if (chunk.Verticies != null)
verticies += chunk.Verticies.VertexCount;
chunk.Draw(TransparentEffect);
}
}
}
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
@ -214,8 +236,8 @@ namespace TrueCraft.Client.Linux
DejaVu.DrawText(SpriteBatch, 0, 500, string.Format("X: {0}, Y: {1}, Z: {2}", Client.Position.X, Client.Position.Y, Client.Position.Z));
DejaVu.DrawText(SpriteBatch, 0, 530, string.Format("Yaw: {0}, Pitch: {1}", Client.Yaw, Client.Pitch));
DejaVu.DrawText(SpriteBatch, GraphicsDevice.Viewport.Height - 30, 0,
string.Format("{0} FPS", fps));
DejaVu.DrawText(SpriteBatch, 0, GraphicsDevice.Viewport.Height - 30,
string.Format("{0} FPS, {1} verticies, {1} chunks", fps, verticies, chunks));
SpriteBatch.End();
base.Draw(gameTime);
}