Lighting optimization (caching shadow vertices & only checking hulls in range if the position or range of the light changes), ragdoll optimization, itemcomponent optimization, dragging stunned/dead characters
This commit is contained in:
@@ -50,6 +50,14 @@ namespace Subsurface
|
||||
|
||||
float lastSentVolume;
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Hull";
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsLinkable
|
||||
{
|
||||
get { return true; }
|
||||
@@ -202,7 +210,7 @@ namespace Subsurface
|
||||
waveY[(int)(position.X - rect.X) / WaveWidth] = 100.0f;
|
||||
Volume = Volume + 1500.0f;
|
||||
}
|
||||
else if (PlayerInput.GetMouseState.RightButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
|
||||
else if (PlayerInput.RightButtonDown())
|
||||
{
|
||||
Volume = Volume - 1500.0f;
|
||||
}
|
||||
@@ -210,12 +218,11 @@ namespace Subsurface
|
||||
}
|
||||
|
||||
//update client hulls if the amount of water has changed by >10%
|
||||
if (Math.Abs(lastSentVolume-volume)>FullVolume*0.1f)
|
||||
if (Math.Abs(lastSentVolume - volume) > FullVolume * 0.1f)
|
||||
{
|
||||
new Networking.NetworkEvent(ID, false);
|
||||
lastSentVolume = volume;
|
||||
}
|
||||
|
||||
if (!update) return;
|
||||
|
||||
float surfaceY = rect.Y - rect.Height + Volume / rect.Width;
|
||||
|
||||
@@ -852,37 +852,6 @@ int currentTargetIndex = 1;
|
||||
Color.White, 0.0f,
|
||||
Vector2.Zero,
|
||||
SpriteEffects.None, 0.0f);
|
||||
|
||||
//pos = startPosition;
|
||||
//pos.X += Position.X;
|
||||
//pos.Y = -pos.Y - Position.Y;
|
||||
|
||||
//spriteBatch.Draw(shaftTexture,
|
||||
// new Rectangle((int)(pos.X - shaftWidth/2), (int)pos.Y, shaftWidth, 512),
|
||||
// new Rectangle(0, 0, shaftWidth, 256),
|
||||
// Color.White, 0.0f,
|
||||
// Vector2.Zero,
|
||||
// SpriteEffects.None, 0.0f);
|
||||
|
||||
//List<Vector2[]> edges = GetCellEdges(observerPosition, 1, false);
|
||||
|
||||
//foreach (VoronoiCell cell in cells)
|
||||
//{
|
||||
// for (int i = 0; i < cell.bodyVertices.Count - 1; i++)
|
||||
// {
|
||||
// Vector2 start = cell.bodyVertices[i];
|
||||
// start.X += Position.X;
|
||||
// start.Y = -start.Y - Position.Y;
|
||||
// start.X += Rand.Range(-10.0f, 10.0f);
|
||||
|
||||
// Vector2 end = cell.bodyVertices[i + 1];
|
||||
// end.X += Position.X;
|
||||
// end.Y = -end.Y - Position.Y;
|
||||
// end.X += Rand.Range(-10.0f, 10.0f);
|
||||
|
||||
// GUI.DrawLine(spriteBatch, start, end, (cell.body != null && cell.body.Enabled) ? Color.Red : Color.Red);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
public List<VoronoiCell> GetCells(Vector2 pos, int searchDepth = 2)
|
||||
|
||||
@@ -5,11 +5,30 @@ using System.Linq;
|
||||
|
||||
namespace Subsurface.Lights
|
||||
{
|
||||
class CachedShadow
|
||||
{
|
||||
|
||||
public VertexPositionColor[] ShadowVertices;
|
||||
public VertexPositionTexture[] PenumbraVertices;
|
||||
|
||||
public Vector2 LightPos;
|
||||
|
||||
public CachedShadow(VertexPositionColor[] shadowVertices, VertexPositionTexture[] penumbraVertices, Vector2 lightPos)
|
||||
{
|
||||
ShadowVertices = shadowVertices;
|
||||
PenumbraVertices = penumbraVertices;
|
||||
|
||||
LightPos = lightPos;
|
||||
}
|
||||
}
|
||||
|
||||
class ConvexHull
|
||||
{
|
||||
public static List<ConvexHull> list = new List<ConvexHull>();
|
||||
static BasicEffect shadowEffect;
|
||||
static BasicEffect penumbraEffect;
|
||||
|
||||
private Dictionary<LightSource, CachedShadow> cachedShadows;
|
||||
|
||||
private Vector2[] vertices;
|
||||
private int primitiveCount;
|
||||
@@ -47,19 +66,14 @@ namespace Subsurface.Lights
|
||||
penumbraEffect.LightingEnabled = false;
|
||||
penumbraEffect.Texture = TextureLoader.FromFile("Content/Lights/penumbra.png");
|
||||
}
|
||||
|
||||
cachedShadows = new Dictionary<LightSource, CachedShadow>();
|
||||
|
||||
vertices = points;
|
||||
primitiveCount = vertices.Length;
|
||||
|
||||
CalculateDimensions();
|
||||
//indices = new short[primitiveCount * 3];
|
||||
|
||||
//for (int i = 0; i < primitiveCount; i++)
|
||||
//{
|
||||
// indices[3 * i] = (short)i;
|
||||
// indices[3 * i + 1] = (short)((i + 1) % vertexCount);
|
||||
// indices[3 * i + 2] = (short)vertexCount;
|
||||
//}
|
||||
|
||||
backFacing = new bool[primitiveCount];
|
||||
|
||||
Enabled = true;
|
||||
@@ -90,6 +104,8 @@ namespace Subsurface.Lights
|
||||
|
||||
public void Move(Vector2 amount)
|
||||
{
|
||||
cachedShadows.Clear();
|
||||
|
||||
for (int i = 0; i < vertices.Count(); i++)
|
||||
{
|
||||
vertices[i] += amount;
|
||||
@@ -100,6 +116,8 @@ namespace Subsurface.Lights
|
||||
|
||||
public void SetVertices(Vector2[] points)
|
||||
{
|
||||
cachedShadows.Clear();
|
||||
|
||||
vertices = points;
|
||||
}
|
||||
|
||||
@@ -222,25 +240,62 @@ namespace Subsurface.Lights
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawShadows(GraphicsDevice graphicsDevice, Camera cam, LightSource light, Matrix transform, bool los = true)
|
||||
{
|
||||
if (!Enabled) return;
|
||||
|
||||
CachedShadow cachedShadow = null;
|
||||
if (cachedShadows.TryGetValue(light, out cachedShadow))
|
||||
{
|
||||
if (light.Position == cachedShadow.LightPos ||
|
||||
Vector2.DistanceSquared(light.Position, cachedShadow.LightPos) < 1.0f)
|
||||
{
|
||||
shadowVertices = cachedShadow.ShadowVertices;
|
||||
penumbraVertices = cachedShadow.PenumbraVertices;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
CalculateShadowVertices(light.Position, los);
|
||||
cachedShadow.LightPos = light.Position;
|
||||
cachedShadow.ShadowVertices = shadowVertices;
|
||||
cachedShadow.PenumbraVertices = penumbraVertices;
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CalculateShadowVertices(light.Position, los);
|
||||
cachedShadow = new CachedShadow(shadowVertices, penumbraVertices, light.Position);
|
||||
cachedShadows.Add(light, cachedShadow);
|
||||
}
|
||||
|
||||
DrawShadows(graphicsDevice, cam, transform, los);
|
||||
}
|
||||
|
||||
public void DrawShadows(GraphicsDevice graphicsDevice, Camera cam, Vector2 lightSourcePos, Matrix transform, bool los = true)
|
||||
{
|
||||
if (!Enabled) return;
|
||||
|
||||
CalculateShadowVertices(lightSourcePos, los);
|
||||
|
||||
|
||||
DrawShadows(graphicsDevice, cam, transform, los);
|
||||
}
|
||||
|
||||
private void DrawShadows(GraphicsDevice graphicsDevice, Camera cam, Matrix transform, bool los = true)
|
||||
{
|
||||
shadowEffect.World = transform;
|
||||
shadowEffect.CurrentTechnique.Passes[0].Apply();
|
||||
|
||||
graphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip, shadowVertices, 0, shadowVertices.Length - 2);
|
||||
|
||||
graphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, shadowVertices, 0, shadowVertices.Length - 2);
|
||||
|
||||
if (los)
|
||||
{
|
||||
penumbraEffect.World = shadowEffect.World;
|
||||
penumbraEffect.CurrentTechnique.Passes[0].Apply();
|
||||
|
||||
#if WINDOWS
|
||||
graphicsDevice.DrawUserPrimitives<VertexPositionTexture>(PrimitiveType.TriangleList, penumbraVertices, 0, 2, VertexPositionTexture.VertexDeclaration);
|
||||
graphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, penumbraVertices, 0, 2, VertexPositionTexture.VertexDeclaration);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,12 +57,13 @@ namespace Subsurface.Lights
|
||||
|
||||
public void DrawLOS(GraphicsDevice graphics, Camera cam, Vector2 pos)
|
||||
{
|
||||
if (!LosEnabled) return;
|
||||
|
||||
Rectangle camView = new Rectangle(cam.WorldView.X, cam.WorldView.Y - cam.WorldView.Height, cam.WorldView.Width, cam.WorldView.Height);
|
||||
|
||||
Matrix shadowTransform = cam.ShaderTransform
|
||||
* Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f;
|
||||
|
||||
if (!LosEnabled) return;
|
||||
foreach (ConvexHull convexHull in ConvexHull.list)
|
||||
{
|
||||
if (!camView.Intersects(convexHull.BoundingBox)) continue;
|
||||
@@ -72,6 +73,14 @@ namespace Subsurface.Lights
|
||||
|
||||
}
|
||||
|
||||
public void OnMapLoaded()
|
||||
{
|
||||
foreach (LightSource light in lights)
|
||||
{
|
||||
light.UpdateHullsInRange();
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawLightmap(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam)
|
||||
{
|
||||
Matrix shadowTransform = cam.ShaderTransform
|
||||
@@ -81,28 +90,28 @@ namespace Subsurface.Lights
|
||||
|
||||
Rectangle viewRect = cam.WorldView;
|
||||
viewRect.Y -= cam.WorldView.Height;
|
||||
|
||||
|
||||
//clear to some small ambient light
|
||||
graphics.Clear(AmbientLight);
|
||||
|
||||
foreach (LightSource light in lights)
|
||||
{
|
||||
if (light.Color.A < 0.01f || light.Range < 0.01f) continue;
|
||||
//clear alpha to 1
|
||||
ClearAlphaToOne(graphics, spriteBatch);
|
||||
|
||||
if (light.Color.A < 0.01f || light.Range < 0.01f || light.hullsInRange.Count == 0) continue;
|
||||
if (!MathUtils.CircleIntersectsRectangle(light.Position, light.Range, viewRect)) continue;
|
||||
|
||||
|
||||
//clear alpha to 1
|
||||
ClearAlphaToOne(graphics, spriteBatch);
|
||||
|
||||
//draw all shadows
|
||||
//write only to the alpha channel, which sets alpha to 0
|
||||
graphics.RasterizerState = RasterizerState.CullNone;
|
||||
graphics.BlendState = CustomBlendStates.WriteToAlpha;
|
||||
|
||||
foreach (ConvexHull ch in ConvexHull.list)
|
||||
foreach (ConvexHull ch in light.hullsInRange)
|
||||
{
|
||||
if (!MathUtils.CircleIntersectsRectangle(light.Position, light.Range, ch.BoundingBox)) continue;
|
||||
//if (!MathUtils.CircleIntersectsRectangle(light.Position, light.Range, ch.BoundingBox)) continue;
|
||||
//draw shadow
|
||||
ch.DrawShadows(graphics, cam, light.Position, shadowTransform, false);
|
||||
ch.DrawShadows(graphics, cam, light, shadowTransform, false);
|
||||
}
|
||||
|
||||
//draw the light shape
|
||||
@@ -111,6 +120,20 @@ namespace Subsurface.Lights
|
||||
light.Draw(spriteBatch);
|
||||
spriteBatch.End();
|
||||
}
|
||||
|
||||
//ClearAlphaToOne(graphics, spriteBatch);
|
||||
//spriteBatch.Begin(SpriteSortMode.Immediate, CustomBlendStates.MultiplyWithAlpha, null, null, null, null, cam.Transform);
|
||||
|
||||
//foreach (LightSource light in lights)
|
||||
//{
|
||||
// if (light.Color.A < 0.01f || light.Range < 0.01f || light.hullsInRange.Count > 0) continue;
|
||||
// if (!MathUtils.CircleIntersectsRectangle(light.Position, light.Range, viewRect)) continue;
|
||||
|
||||
// light.Draw(spriteBatch);
|
||||
//}
|
||||
|
||||
//spriteBatch.End();
|
||||
|
||||
//clear alpha, to avoid messing stuff up later
|
||||
ClearAlphaToOne(graphics, spriteBatch);
|
||||
graphics.SetRenderTarget(null);
|
||||
|
||||
@@ -11,13 +11,26 @@ namespace Subsurface.Lights
|
||||
{
|
||||
private static Texture2D lightTexture;
|
||||
|
||||
public List<ConvexHull> hullsInRange;
|
||||
|
||||
private Color color;
|
||||
|
||||
private float range;
|
||||
|
||||
private Texture2D texture;
|
||||
|
||||
public Vector2 Position;
|
||||
private Vector2 position;
|
||||
public Vector2 Position
|
||||
{
|
||||
get { return position; }
|
||||
set
|
||||
{
|
||||
if (position == value) return;
|
||||
|
||||
position = value;
|
||||
UpdateHullsInRange();
|
||||
}
|
||||
}
|
||||
|
||||
public Color Color
|
||||
{
|
||||
@@ -30,13 +43,19 @@ namespace Subsurface.Lights
|
||||
get { return range; }
|
||||
set
|
||||
{
|
||||
range = MathHelper.Clamp(value, 0.0f, 2048.0f);
|
||||
float newRange = MathHelper.Clamp(value, 0.0f, 2048.0f);
|
||||
if (range == newRange) return;
|
||||
range = newRange;
|
||||
|
||||
UpdateHullsInRange();
|
||||
}
|
||||
}
|
||||
|
||||
public LightSource(Vector2 position, float range, Color color)
|
||||
{
|
||||
Position = position;
|
||||
hullsInRange = new List<ConvexHull>();
|
||||
|
||||
this.position = position;
|
||||
this.range = range;
|
||||
this.color = color;
|
||||
|
||||
@@ -50,10 +69,21 @@ namespace Subsurface.Lights
|
||||
GameMain.LightManager.AddLight(this);
|
||||
}
|
||||
|
||||
public void UpdateHullsInRange()
|
||||
{
|
||||
hullsInRange.Clear();
|
||||
if (range < 1.0f) return;
|
||||
|
||||
foreach (ConvexHull ch in ConvexHull.list)
|
||||
{
|
||||
if (MathUtils.CircleIntersectsRectangle(position, range, ch.BoundingBox)) hullsInRange.Add(ch);
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
Vector2 center = new Vector2(lightTexture.Width / 2, lightTexture.Height / 2);
|
||||
float scale = range / ((float)lightTexture.Width / 2.0f);
|
||||
float scale = range / (lightTexture.Width / 2.0f);
|
||||
spriteBatch.Draw(lightTexture, new Vector2(Position.X, -Position.Y), null, color, 0, center, scale, SpriteEffects.None, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -192,6 +192,8 @@ namespace Subsurface
|
||||
}
|
||||
}
|
||||
|
||||
static Dictionary<string, float> timeElapsed = new Dictionary<string, float>();
|
||||
|
||||
/// <summary>
|
||||
/// Call Update() on every object in Entity.list
|
||||
/// </summary>
|
||||
@@ -202,10 +204,46 @@ namespace Subsurface
|
||||
item.Updated = false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mapEntityList.Count; i++)
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
mapEntityList[i].Update(cam, deltaTime);
|
||||
hull.Update(cam, deltaTime);
|
||||
}
|
||||
|
||||
foreach (Gap gap in Gap.GapList)
|
||||
{
|
||||
gap.Update(cam, deltaTime);
|
||||
}
|
||||
|
||||
foreach (Item item in Item.itemList)
|
||||
{
|
||||
item.Update(cam, deltaTime);
|
||||
}
|
||||
|
||||
//Stopwatch sw = new Stopwatch();
|
||||
|
||||
//for (int i = 0; i < mapEntityList.Count; i++)
|
||||
//{
|
||||
// sw.Restart();
|
||||
// mapEntityList[i].Update(cam, deltaTime);
|
||||
// sw.Stop();
|
||||
|
||||
// if (timeElapsed.ContainsKey(mapEntityList[i].Name))
|
||||
// {
|
||||
// float asd = 0.0f;
|
||||
// timeElapsed.TryGetValue(mapEntityList[i].Name, out asd);
|
||||
// asd += sw.ElapsedTicks;
|
||||
|
||||
// timeElapsed.Remove(mapEntityList[i].Name);
|
||||
// timeElapsed.Add(mapEntityList[i].Name, asd);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// timeElapsed.Add(mapEntityList[i].Name, sw.ElapsedTicks);
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public virtual void Update(Camera cam, float deltaTime) { }
|
||||
|
||||
@@ -609,7 +609,7 @@ namespace Subsurface
|
||||
subBody = new SubmarineBody(this);
|
||||
|
||||
MapEntity.OnMapLoaded();
|
||||
|
||||
|
||||
foreach (Item item in Item.itemList)
|
||||
{
|
||||
foreach (ItemComponent ic in item.components)
|
||||
@@ -618,6 +618,8 @@ namespace Subsurface
|
||||
}
|
||||
}
|
||||
|
||||
GameMain.LightManager.OnMapLoaded();
|
||||
|
||||
ID = int.MaxValue-10;
|
||||
|
||||
loaded = this;
|
||||
|
||||
@@ -29,6 +29,14 @@ namespace Subsurface
|
||||
set { spawnType = value; }
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return "WayPoint";
|
||||
}
|
||||
}
|
||||
|
||||
public string[] IdCardTags
|
||||
{
|
||||
get { return idCardTags; }
|
||||
|
||||
Reference in New Issue
Block a user