Files
LuaCsForBarotraumaEP/Subsurface/Map/Lights/LightManager.cs

140 lines
4.7 KiB
C#

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;
namespace Subsurface.Lights
{
class LightManager
{
public static Vector2 ViewPos;
public Color AmbientLight;
RenderTarget2D lightMap;
private static Texture2D alphaClearTexture;
private List<LightSource> lights;
public bool FowEnabled = true;
public bool LightingEnabled = true;
public RenderTarget2D LightMap
{
get { return lightMap; }
}
public LightManager(GraphicsDevice graphics)
{
lights = new List<LightSource>();
AmbientLight = new Color(80, 80, 80, 255);
var pp = graphics.PresentationParameters;
lightMap = new RenderTarget2D(graphics, Game1.GraphicsWidth, Game1.GraphicsHeight, false,
pp.BackBufferFormat, pp.DepthStencilFormat, pp.MultiSampleCount,
RenderTargetUsage.DiscardContents);
if (alphaClearTexture==null)
{
alphaClearTexture = Game1.TextureLoader.FromFile("Content/Lights/alphaOne.png");
}
}
public void AddLight(LightSource light)
{
lights.Add(light);
}
public void RemoveLight(LightSource light)
{
lights.Remove(light);
}
public void DrawFow(GraphicsDevice graphics, Camera cam, Vector2 pos)
{
if (!FowEnabled) return;
foreach (ConvexHull convexHull in ConvexHull.list)
{
convexHull.DrawShadows(graphics, cam, pos);
}
}
public void DrawLightmap(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam)
{
graphics.SetRenderTarget(lightMap);
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 (!MathUtils.CircleIntersectsRectangle(light.Position, light.Range, viewRect)) continue;
//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)
{
//draw shadow
ch.DrawShadows(graphics, cam, light.Position, false);
}
//draw the light shape
//where Alpha is 0, nothing will be written
spriteBatch.Begin(SpriteSortMode.Immediate, CustomBlendStates.MultiplyWithAlpha, null, null, null, null, cam.Transform);
light.Draw(spriteBatch);
spriteBatch.End();
}
//clear alpha, to avoid messing stuff up later
ClearAlphaToOne(graphics, spriteBatch);
graphics.SetRenderTarget(null);
}
private void ClearAlphaToOne(GraphicsDevice graphics, SpriteBatch spriteBatch)
{
spriteBatch.Begin(SpriteSortMode.Immediate, CustomBlendStates.WriteToAlpha);
spriteBatch.Draw(alphaClearTexture, new Rectangle(0, 0,graphics.Viewport.Width, graphics.Viewport.Height), Color.White);
spriteBatch.End();
}
}
class CustomBlendStates
{
static CustomBlendStates()
{
Multiplicative = new BlendState();
Multiplicative.ColorSourceBlend = Multiplicative.AlphaSourceBlend = Blend.Zero;
Multiplicative.ColorDestinationBlend = Multiplicative.AlphaDestinationBlend = Blend.SourceColor;
Multiplicative.ColorBlendFunction = Multiplicative.AlphaBlendFunction = BlendFunction.Add;
WriteToAlpha = new BlendState();
WriteToAlpha.ColorWriteChannels = ColorWriteChannels.Alpha;
MultiplyWithAlpha = new BlendState();
MultiplyWithAlpha.ColorDestinationBlend = MultiplyWithAlpha.AlphaDestinationBlend = Blend.One;
MultiplyWithAlpha.ColorSourceBlend = MultiplyWithAlpha.AlphaSourceBlend = Blend.DestinationAlpha;
}
public static BlendState Multiplicative { get; private set; }
public static BlendState WriteToAlpha { get; private set; }
public static BlendState MultiplyWithAlpha { get; private set; }
}
}