From 844097b132a6a777ef925205cce3852828b19706 Mon Sep 17 00:00:00 2001 From: Regalis Date: Sat, 25 Feb 2017 21:24:38 +0200 Subject: [PATCH] Initial steps in making the light rendering use light volumes instead of shadow volumes to allow rendering the lights in one batch. So far just disabled shadow rendering and cleaned up some unnecessary stuff --- Subsurface/Source/Map/Lights/ConvexHull.cs | 53 +++++++++++++++ Subsurface/Source/Map/Lights/LightManager.cs | 37 +--------- Subsurface/Source/Map/Lights/LightSource.cs | 71 ++++---------------- 3 files changed, 70 insertions(+), 91 deletions(-) diff --git a/Subsurface/Source/Map/Lights/ConvexHull.cs b/Subsurface/Source/Map/Lights/ConvexHull.cs index c48285988..d0e3fb589 100644 --- a/Subsurface/Source/Map/Lights/ConvexHull.cs +++ b/Subsurface/Source/Map/Lights/ConvexHull.cs @@ -397,6 +397,59 @@ namespace Barotrauma.Lights } } + public static List GetHullsInRange(Vector2 position, float range, Submarine ParentSub) + { + List list = new List(); + + foreach (ConvexHullList chList in ConvexHull.HullLists) + { + Vector2 lightPos = position; + if (ParentSub == null) + { + //light and the convexhull are both outside + if (chList.Submarine == null) + { + list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox))); + + } + //light is outside, convexhull inside a sub + else + { + if (!MathUtils.CircleIntersectsRectangle(lightPos - chList.Submarine.WorldPosition, range, chList.Submarine.Borders)) continue; + + lightPos -= (chList.Submarine.WorldPosition - chList.Submarine.HiddenSubPosition); + + list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox))); + } + } + else + { + //light is inside, convexhull outside + if (chList.Submarine == null) continue; + + //light and convexhull are both inside the same sub + if (chList.Submarine == ParentSub) + { + list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox))); + } + //light and convexhull are inside different subs + else + { + lightPos -= (chList.Submarine.Position - ParentSub.Position); + + Rectangle subBorders = chList.Submarine.Borders; + subBorders.Location += chList.Submarine.HiddenSubPosition.ToPoint() - new Point(0, chList.Submarine.Borders.Height); + + if (!MathUtils.CircleIntersectsRectangle(lightPos, range, subBorders)) continue; + + list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox))); + } + } + } + + return list; + } + public void DrawShadows(GraphicsDevice graphicsDevice, Camera cam, LightSource light, Matrix transform, bool los = true) { if (!Enabled) return; diff --git a/Subsurface/Source/Map/Lights/LightManager.cs b/Subsurface/Source/Map/Lights/LightManager.cs index b3d4c8382..4040be2ab 100644 --- a/Subsurface/Source/Map/Lights/LightManager.cs +++ b/Subsurface/Source/Map/Lights/LightManager.cs @@ -133,45 +133,19 @@ namespace Barotrauma.Lights //clear to some small ambient light graphics.Clear(AmbientLight); + spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, null, null, null, cam.Transform); + foreach (LightSource light in lights) { if (light.Color.A < 1 || light.Range < 1.0f || !light.CastShadows) continue; if (!MathUtils.CircleIntersectsRectangle(light.WorldPosition, 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; - light.DrawShadows(graphics, cam, shadowTransform); - - //draw the light shape - //where Alpha is 0, nothing will be written - spriteBatch.Begin(SpriteSortMode.Deferred, CustomBlendStates.MultiplyWithAlpha, null, null, null, null, cam.Transform); light.Draw(spriteBatch); - spriteBatch.End(); } - - ClearAlphaToOne(graphics, spriteBatch); - - spriteBatch.Begin(SpriteSortMode.Deferred, CustomBlendStates.MultiplyWithAlpha, null, null, null, null, cam.Transform); - GameMain.ParticleManager.Draw(spriteBatch, false, Particles.ParticleBlendState.Additive); - - foreach (LightSource light in lights) - { - if (light.Color.A < 1 || light.Range < 1.0f || light.CastShadows) continue; - //if (!MathUtils.CircleIntersectsRectangle(light.WorldPosition, light.Range, viewRect)) continue; - - light.Draw(spriteBatch); - } - if (Character.Controlled != null) { if (Character.Controlled.ClosestItem != null) @@ -185,10 +159,6 @@ namespace Barotrauma.Lights Character.Controlled.ClosestCharacter.Draw(spriteBatch); } } - spriteBatch.End(); - - - spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, null, null, null, cam.Transform); foreach (Hull hull in smoothedHullAmbientLights.Keys) { @@ -207,7 +177,6 @@ namespace Barotrauma.Lights spriteBatch.End(); - //clear alpha, to avoid messing stuff up later ClearAlphaToOne(graphics, spriteBatch); @@ -253,7 +222,7 @@ namespace Barotrauma.Lights Matrix shadowTransform = cam.ShaderTransform * Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f; - var convexHulls = LightSource.GetHullsInRange(viewTarget.Position, cam.WorldView.Width*0.75f, viewTarget.Submarine); + var convexHulls = ConvexHull.GetHullsInRange(viewTarget.Position, cam.WorldView.Width*0.75f, viewTarget.Submarine); if (convexHulls != null) { diff --git a/Subsurface/Source/Map/Lights/LightSource.cs b/Subsurface/Source/Map/Lights/LightSource.cs index f6d21525d..0b64f0206 100644 --- a/Subsurface/Source/Map/Lights/LightSource.cs +++ b/Subsurface/Source/Map/Lights/LightSource.cs @@ -136,7 +136,7 @@ namespace Barotrauma.Lights GameMain.LightManager.AddLight(this); } - public void DrawShadows(GraphicsDevice graphics, Camera cam, Matrix shadowTransform) + /*public void DrawShadows(GraphicsDevice graphics, Camera cam, Matrix shadowTransform) { if (!CastShadows) return; if (range < 1.0f || color.A < 0.01f) return; @@ -161,9 +161,9 @@ namespace Barotrauma.Lights foreach (ConvexHull ch in outsideHulls) { ch.DrawShadows(graphics, cam, this, shadowTransform, false); - } - } - + } + } + private List GetHullsInRange(Submarine sub) { //find the current list of hulls in range @@ -237,62 +237,20 @@ namespace Barotrauma.Lights } return chList.List; - } + }*/ - public static List GetHullsInRange(Vector2 position, float range, Submarine ParentSub) + private void CalculateFanVertices() { - List list = new List(); + if (!CastShadows) return; + if (range < 1.0f || color.A < 0.01f) return; - foreach (ConvexHullList chList in ConvexHull.HullLists) - { - Vector2 lightPos = position; - if (ParentSub == null) - { - //light and the convexhull are both outside - if (chList.Submarine == null) - { - list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox))); - - } - //light is outside, convexhull inside a sub - else - { - if (!MathUtils.CircleIntersectsRectangle(lightPos - chList.Submarine.WorldPosition, range, chList.Submarine.Borders)) continue; - - lightPos -= (chList.Submarine.WorldPosition - chList.Submarine.HiddenSubPosition); - - list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox))); - } - } - else - { - //light is inside, convexhull outside - if (chList.Submarine == null) continue; - - //light and convexhull are both inside the same sub - if (chList.Submarine == ParentSub) - { - list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox))); - } - //light and convexhull are inside different subs - else - { - lightPos -= (chList.Submarine.Position - ParentSub.Position); - - Rectangle subBorders = chList.Submarine.Borders; - subBorders.Location += chList.Submarine.HiddenSubPosition.ToPoint() - new Point(0, chList.Submarine.Borders.Height); - - if (!MathUtils.CircleIntersectsRectangle(lightPos, range, subBorders)) continue; - - list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox))); - } - } - } - - - return list; + var hulls = ConvexHull.GetHullsInRange(position, range, ParentSub); + + //TODO: calculate fan based on hulls + + //http://www.redblobgames.com/articles/visibility/ + //http://roy-t.nl/index.php/2014/02/27/2d-lighting-and-shadows-preview/ } - public void Draw(SpriteBatch spriteBatch) { @@ -323,7 +281,6 @@ namespace Barotrauma.Lights if (LightSprite != null) { LightSprite.Draw(spriteBatch, drawPos, Color, LightSprite.Origin, -Rotation, 1, SpriteEffect); - } }