diff --git a/DepthsBelow.sln b/DepthsBelow.sln
index 73818fa..176dd07 100644
--- a/DepthsBelow.sln
+++ b/DepthsBelow.sln
@@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AStar", "AStar\AStar.csproj
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{FF7D4CEE-291C-4F85-9630-977446A466D3}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Krypton", "Krypton v2.0\Krypton\Krypton.csproj", "{B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -69,12 +71,23 @@ Global
{CD3F949D-54AA-4D38-99DB-92905A375D84}.Release|Mixed Platforms.Build.0 = Release|x86
{CD3F949D-54AA-4D38-99DB-92905A375D84}.Release|x86.ActiveCfg = Release|x86
{CD3F949D-54AA-4D38-99DB-92905A375D84}.Release|x86.Build.0 = Release|x86
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}.Debug|x86.ActiveCfg = Debug|x86
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}.Debug|x86.Build.0 = Debug|x86
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}.Release|Any CPU.ActiveCfg = Release|x86
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}.Release|Mixed Platforms.Build.0 = Release|x86
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}.Release|x86.ActiveCfg = Release|x86
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
- {EC3F6988-459C-4783-89E9-F34C0CC731C7} = {FF7D4CEE-291C-4F85-9630-977446A466D3}
{CD3F949D-54AA-4D38-99DB-92905A375D84} = {FF7D4CEE-291C-4F85-9630-977446A466D3}
+ {EC3F6988-459C-4783-89E9-F34C0CC731C7} = {FF7D4CEE-291C-4F85-9630-977446A466D3}
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3} = {FF7D4CEE-291C-4F85-9630-977446A466D3}
EndGlobalSection
EndGlobal
diff --git a/Krypton v2.0/Krypton.sln b/Krypton v2.0/Krypton.sln
new file mode 100755
index 0000000..db89da7
--- /dev/null
+++ b/Krypton v2.0/Krypton.sln
@@ -0,0 +1,38 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Krypton", "Krypton\Krypton.csproj", "{B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KryptonTestbed", "KryptonTestbed\KryptonTestbed\KryptonTestbed.csproj", "{E9787BEE-7290-4C74-B919-79DC70AABE87}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KryptonTestbedContent", "KryptonTestbed\KryptonTestbedContent\KryptonTestbedContent.contentproj", "{EA878F1A-4714-4377-8E6A-4947ACFF386A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}.Debug|x86.ActiveCfg = Debug|x86
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}.Debug|x86.Build.0 = Debug|x86
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}.Release|Any CPU.ActiveCfg = Release|x86
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}.Release|x86.ActiveCfg = Release|x86
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}.Release|x86.Build.0 = Release|x86
+ {E9787BEE-7290-4C74-B919-79DC70AABE87}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {E9787BEE-7290-4C74-B919-79DC70AABE87}.Debug|x86.ActiveCfg = Debug|x86
+ {E9787BEE-7290-4C74-B919-79DC70AABE87}.Debug|x86.Build.0 = Debug|x86
+ {E9787BEE-7290-4C74-B919-79DC70AABE87}.Release|Any CPU.ActiveCfg = Release|x86
+ {E9787BEE-7290-4C74-B919-79DC70AABE87}.Release|x86.ActiveCfg = Release|x86
+ {E9787BEE-7290-4C74-B919-79DC70AABE87}.Release|x86.Build.0 = Release|x86
+ {EA878F1A-4714-4377-8E6A-4947ACFF386A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EA878F1A-4714-4377-8E6A-4947ACFF386A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {EA878F1A-4714-4377-8E6A-4947ACFF386A}.Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {EA878F1A-4714-4377-8E6A-4947ACFF386A}.Release|x86.ActiveCfg = Debug|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Krypton v2.0/Krypton/Common/BoundingRect.cs b/Krypton v2.0/Krypton/Common/BoundingRect.cs
new file mode 100755
index 0000000..6443c7f
--- /dev/null
+++ b/Krypton v2.0/Krypton/Common/BoundingRect.cs
@@ -0,0 +1,278 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Microsoft.Xna.Framework;
+using System.Globalization;
+using System.Runtime.InteropServices;
+
+namespace Krypton.Common
+{
+ ///
+ /// Much like Rectangle, but stored as two Vector2s
+ ///
+ public struct BoundingRect
+ {
+ public Vector2 Min;
+ public Vector2 Max;
+
+ public float Left { get { return this.Min.X; } }
+ public float Right { get { return this.Max.X; } }
+ public float Top { get { return this.Max.Y; } }
+ public float Bottom { get { return this.Min.Y; } }
+
+ public float Width { get { return this.Max.X - this.Min.X; } }
+ public float Height { get { return this.Max.Y - this.Min.Y; } }
+
+ private static BoundingRect mEmpty;
+ private static BoundingRect mMinMax;
+
+ static BoundingRect()
+ {
+ BoundingRect.mEmpty = new BoundingRect();
+ BoundingRect.mMinMax = new BoundingRect(Vector2.One * float.MinValue, Vector2.One * float.MaxValue);
+ }
+
+ public Vector2 Center
+ {
+ get { return (this.Min + this.Max) / 2; }
+ }
+
+ public static BoundingRect Empty
+ {
+ get { return BoundingRect.mEmpty; }
+ }
+
+
+ public static BoundingRect MinMax
+ {
+ get { return BoundingRect.mMinMax; }
+ }
+
+ public bool IsZero
+ {
+ get
+ {
+ return
+ (this.Min.X == 0) &&
+ (this.Min.Y == 0) &&
+ (this.Max.X == 0) &&
+ (this.Max.Y == 0);
+ }
+ }
+
+ public BoundingRect(float x, float y, float width, float height)
+ {
+ this.Min.X = x;
+ this.Min.Y = y;
+ this.Max.X = x + width;
+ this.Max.Y = y + height;
+ }
+
+ public BoundingRect(Vector2 min, Vector2 max)
+ {
+ this.Min = min;
+ this.Max = max;
+ }
+
+ public bool Contains(float x, float y)
+ {
+ return
+ (this.Min.X <= x) &&
+ (this.Min.Y <= y) &&
+ (this.Max.X >= x) &&
+ (this.Max.Y >= y);
+ }
+
+ public bool Contains(Vector2 vector)
+ {
+ return
+ (this.Min.X <= vector.X) &&
+ (this.Min.Y <= vector.Y) &&
+ (this.Max.X >= vector.X) &&
+ (this.Max.Y >= vector.Y);
+ }
+
+ public void Contains(ref Vector2 rect, out bool result)
+ {
+ result =
+ (this.Min.X <= rect.X) &&
+ (this.Min.Y <= rect.Y) &&
+ (this.Max.X >= rect.X) &&
+ (this.Max.Y >= rect.Y);
+ }
+
+ public bool Contains(BoundingRect rect)
+ {
+ return
+ (this.Min.X <= rect.Min.X) &&
+ (this.Min.Y <= rect.Min.Y) &&
+ (this.Max.X >= rect.Max.X) &&
+ (this.Max.Y >= rect.Max.Y);
+ }
+
+ public void Contains(ref BoundingRect rect, out bool result)
+ {
+ result =
+ (this.Min.X <= rect.Min.X) &&
+ (this.Min.Y <= rect.Min.Y) &&
+ (this.Max.X >= rect.Max.X) &&
+ (this.Max.Y >= rect.Max.Y) ;
+ }
+
+ public bool Intersects(BoundingRect rect)
+ {
+ return
+ (this.Min.X < rect.Max.X) &&
+ (this.Min.Y < rect.Max.Y) &&
+ (this.Max.X > rect.Min.X) &&
+ (this.Max.Y > rect.Min.Y);
+ }
+
+ public void Intersects(ref BoundingRect rect, out bool result)
+ {
+ result =
+ (this.Min.X < rect.Max.X) &&
+ (this.Min.Y < rect.Max.Y) &&
+ (this.Max.X > rect.Min.X) &&
+ (this.Max.Y > rect.Min.Y);
+ }
+
+ public static BoundingRect Intersect(BoundingRect rect1, BoundingRect rect2)
+ {
+ BoundingRect result;
+
+ float num8 = rect1.Max.X;
+ float num7 = rect2.Max.X;
+ float num6 = rect1.Max.Y;
+ float num5 = rect2.Max.Y;
+ float num2 = (rect1.Min.X > rect2.Min.X) ? rect1.Min.X : rect2.Min.X;
+ float num = (rect1.Min.Y > rect2.Min.Y) ? rect1.Min.Y : rect2.Min.Y;
+ float num4 = (num8 < num7) ? num8 : num7;
+ float num3 = (num6 < num5) ? num6 : num5;
+
+ if ((num4 > num2) && (num3 > num))
+ {
+ result.Min.X = num2;
+ result.Min.Y = num;
+ result.Max.X = num4;
+ result.Max.Y = num3;
+
+ return result;
+ }
+
+ result.Min.X = 0;
+ result.Min.Y = 0;
+ result.Max.X = 0;
+ result.Max.Y = 0;
+
+ return result;
+ }
+
+ public static void Intersect(ref BoundingRect rect1, ref BoundingRect rect2, out BoundingRect result)
+ {
+ float num8 = rect1.Max.X;
+ float num7 = rect2.Max.X;
+ float num6 = rect1.Max.Y;
+ float num5 = rect2.Max.Y;
+ float num2 = (rect1.Min.X > rect2.Min.X) ? rect1.Min.X : rect2.Min.X;
+ float num = (rect1.Min.Y > rect2.Min.Y) ? rect1.Min.Y : rect2.Min.Y;
+ float num4 = (num8 < num7) ? num8 : num7;
+ float num3 = (num6 < num5) ? num6 : num5;
+
+ if ((num4 > num2) && (num3 > num))
+ {
+ result.Min.X = num2;
+ result.Min.Y = num;
+ result.Max.X = num4;
+ result.Max.Y = num3;
+ }
+
+ result.Min.X = 0;
+ result.Min.Y = 0;
+ result.Max.X = 0;
+ result.Max.Y = 0;
+ }
+
+ public static BoundingRect Union(BoundingRect rect1, BoundingRect rect2)
+ {
+ BoundingRect result;
+
+ float num6 = rect1.Max.X;
+ float num5 = rect2.Max.X;
+ float num4 = rect1.Max.Y;
+ float num3 = rect2.Max.Y;
+ float num2 = (rect1.Min.X < rect2.Min.X) ? rect1.Min.X : rect2.Min.X;
+ float num = (rect1.Min.Y < rect2.Min.Y) ? rect1.Min.Y : rect2.Min.Y;
+ float num8 = (num6 > num5) ? num6 : num5;
+ float num7 = (num4 > num3) ? num4 : num3;
+
+ result.Min.X = num2;
+ result.Min.Y = num;
+ result.Max.X = num8;
+ result.Max.Y = num7;
+
+ return result;
+ }
+
+ public static void Union(ref BoundingRect rect1, ref BoundingRect rect2, out BoundingRect result)
+ {
+ float num6 = rect1.Max.X;
+ float num5 = rect2.Max.X;
+ float num4 = rect1.Max.Y;
+ float num3 = rect2.Max.Y;
+ float num2 = (rect1.Min.X < rect2.Min.X) ? rect1.Min.X : rect2.Min.X;
+ float num = (rect1.Min.Y < rect2.Min.Y) ? rect1.Min.Y : rect2.Min.Y;
+ float num8 = (num6 > num5) ? num6 : num5;
+ float num7 = (num4 > num3) ? num4 : num3;
+
+ result.Min.X = num2;
+ result.Min.Y = num;
+ result.Max.X = num8;
+ result.Max.Y = num7;
+ }
+
+ public bool Equals(BoundingRect other)
+ {
+ return
+ (this.Min.X == other.Min.X) &&
+ (this.Min.Y == other.Min.Y) &&
+ (this.Max.X == other.Max.X) &&
+ (this.Max.Y == other.Max.Y);
+ }
+
+ public override int GetHashCode()
+ {
+ return this.Min.GetHashCode() + this.Max.GetHashCode();
+ }
+
+ public static bool operator ==(BoundingRect a, BoundingRect b)
+ {
+ return
+ (a.Min.X == b.Min.X) &&
+ (a.Min.Y == b.Min.Y) &&
+ (a.Max.X == b.Max.X) &&
+ (a.Max.Y == b.Max.Y);
+ }
+
+ public static bool operator !=(BoundingRect a, BoundingRect b)
+ {
+ return
+ (a.Min.X != b.Min.X) ||
+ (a.Min.Y != b.Min.Y) ||
+ (a.Max.X != b.Max.X) ||
+ (a.Max.Y != b.Max.Y);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is BoundingRect)
+ {
+ return this == (BoundingRect)obj;
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/Krypton v2.0/Krypton/Krypton.csproj b/Krypton v2.0/Krypton/Krypton.csproj
new file mode 100755
index 0000000..0e1209d
--- /dev/null
+++ b/Krypton v2.0/Krypton/Krypton.csproj
@@ -0,0 +1,98 @@
+
+
+
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}
+ {6D335F3A-9D43-41b4-9D22-F6F17C4BE596};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Debug
+ x86
+ Library
+ Properties
+ Krypton
+ Krypton
+ v4.0
+ Client
+ v4.0
+ Windows
+ HiDef
+ f22a3b67-7b26-4bcf-9fa4-831713f618f0
+ Library
+
+
+
+
+
+
+
+
+
+
+ true
+ full
+ false
+ bin\x86\Debug
+ DEBUG;TRACE;WINDOWS
+ prompt
+ 4
+ true
+ false
+ x86
+ false
+
+
+ pdbonly
+ true
+ bin\x86\Release
+ TRACE;WINDOWS
+ prompt
+ 4
+ true
+ false
+ x86
+ true
+
+
+
+
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ 4.0
+ False
+
+
+ 4.0
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Krypton v2.0/Krypton/KryptonEngine.cs b/Krypton v2.0/Krypton/KryptonEngine.cs
new file mode 100755
index 0000000..1bc77bc
--- /dev/null
+++ b/Krypton v2.0/Krypton/KryptonEngine.cs
@@ -0,0 +1,423 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Audio;
+using Microsoft.Xna.Framework.Content;
+using Microsoft.Xna.Framework.GamerServices;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+using Microsoft.Xna.Framework.Media;
+
+using Krypton.Lights;
+using Krypton.Common;
+
+
+namespace Krypton
+{
+ public enum LightMapSize
+ {
+ Full = 1,
+ Fourth = 2,
+ Eighth = 4,
+ }
+
+ ///
+ /// A GPU-based 2D lighting engine
+ ///
+ public class KryptonEngine : DrawableGameComponent
+ {
+ // The Krypton Effect
+ private string mEffectAssetName;
+ private Effect mEffect;
+ private CullMode mCullMode = CullMode.CullCounterClockwiseFace;
+
+ // The goods
+ private List mHulls = new List();
+ private List mLights = new List();
+
+ // World View Projection matrix, and it's min and max view bounds
+ private Matrix mWVP = Matrix.Identity;
+ private bool mSpriteBatchCompatabilityEnabled = false;
+ private BoundingRect mBounds = BoundingRect.MinMax;
+
+ // Blur
+ private float mBluriness = 0.25f;
+ private RenderTarget2D mMapBlur;
+
+ // Light maps
+ private RenderTarget2D mMap;
+ private Color mAmbientColor = new Color(35,35,35);
+ private LightMapSize mLightMapSize = LightMapSize.Full;
+
+ ///
+ /// Krypton's render helper. It helps render. It also needs to be re-written.
+ ///
+ public KryptonRenderHelper RenderHelper { get; private set; }
+
+ ///
+ /// Gets or sets a value indicating how Krypton should cull geometry. The default value is CullMode.CounterClockwise
+ ///
+ public CullMode CullMode
+ {
+ get { return this.mCullMode; }
+ set { this.mCullMode = value; }
+ }
+
+ ///
+ /// The collection of lights krypton uses to render shadows
+ ///
+ public List Lights { get { return this.mLights; } }
+
+ ///
+ /// The collection of hulls krypton uses to render shadows
+ ///
+ public List Hulls { get { return this.mHulls; } }
+
+ ///
+ /// Gets or sets the matrix used to draw the light map. This should match your scene's matrix.
+ ///
+ public Matrix Matrix
+ {
+ get { return this.mWVP; }
+ set
+ {
+ if (this.mWVP != value)
+ {
+ this.mWVP = value;
+
+ // This is totally ghetto, but it works for now. :)
+ // Compute the world-space bounds of the given matrix
+ var inverse = Matrix.Invert(value);
+
+ var v1 = Vector2.Transform(new Vector2(1, 1), inverse);
+ var v2 = Vector2.Transform(new Vector2(1, -1), inverse);
+ var v3 = Vector2.Transform(new Vector2(-1, -1), inverse);
+ var v4 = Vector2.Transform(new Vector2(-1, 1), inverse);
+
+ this.mBounds.Min = v1;
+ this.mBounds.Min = Vector2.Min(this.mBounds.Min, v2);
+ this.mBounds.Min = Vector2.Min(this.mBounds.Min, v3);
+ this.mBounds.Min = Vector2.Min(this.mBounds.Min, v4);
+
+ this.mBounds.Max = v1;
+ this.mBounds.Max = Vector2.Max(this.mBounds.Max, v2);
+ this.mBounds.Max = Vector2.Max(this.mBounds.Max, v3);
+ this.mBounds.Max = Vector2.Max(this.mBounds.Max, v4);
+
+ this.mBounds = BoundingRect.MinMax;
+ }
+ }
+ }
+
+ ///
+ /// Gets or sets a value indicating weither or not to use SpriteBatch's matrix when drawing lightmaps
+ ///
+ public bool SpriteBatchCompatablityEnabled
+ {
+ get { return this.mSpriteBatchCompatabilityEnabled; }
+ set { this.mSpriteBatchCompatabilityEnabled = value; }
+ }
+
+ ///
+ /// Ambient color of the light map. Lights + AmbientColor = Final
+ ///
+ public Color AmbientColor
+ {
+ get { return this.mAmbientColor; }
+ set { this.mAmbientColor = value; }
+ }
+
+ ///
+ /// Gets or sets the value used to determine light map size
+ ///
+ public LightMapSize LightMapSize
+ {
+ get { return this.mLightMapSize; }
+ set
+ {
+ if (this.mLightMapSize != value)
+ {
+ this.mLightMapSize = value;
+ this.DisposeRenderTargets();
+ this.CreateRenderTargets();
+ }
+ }
+ }
+
+ ///
+ /// Gets or sets a value indicating how much to blur the final light map. If the value is zero, the lightmap will not be blurred
+ ///
+ public float Bluriness
+ {
+ get { return this.mBluriness; }
+ set { this.mBluriness = Math.Max(0, value); }
+ }
+
+ ///
+ /// Constructs a new instance of krypton
+ ///
+ /// Your game object
+ /// The asset name of Krypton's effect file, which must be included in your content project
+ public KryptonEngine(Game game, string effectAssetName)
+ : base(game)
+ {
+ this.mEffectAssetName = effectAssetName;
+ }
+
+ ///
+ /// Initializes Krpyton, and hooks itself to the graphics device
+ ///
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ this.GraphicsDevice.DeviceReset += new EventHandler(GraphicsDevice_DeviceReset);
+ }
+
+ ///
+ /// Resets kryptons graphics device resources
+ ///
+ private void GraphicsDevice_DeviceReset(object sender, EventArgs e)
+ {
+ this.DisposeRenderTargets();
+ this.CreateRenderTargets();
+ }
+
+ ///
+ /// Load's the graphics related content required to draw light maps
+ ///
+ protected override void LoadContent()
+ {
+ // This needs to better handle content loading...
+ // if the window is resized, Krypton needs to notice.
+ this.mEffect = this.Game.Content.Load(this.mEffectAssetName);
+ this.RenderHelper = new KryptonRenderHelper(this.GraphicsDevice, this.mEffect);
+
+ this.CreateRenderTargets();
+ }
+
+ ///
+ /// Unload's the graphics content required to draw light maps
+ ///
+ protected override void UnloadContent()
+ {
+ this.DisposeRenderTargets();
+ }
+
+ ///
+ /// Creates render targets
+ ///
+ private void CreateRenderTargets()
+ {
+ var targetWidth = GraphicsDevice.Viewport.Width / (int)(this.mLightMapSize);
+ var targetHeight = GraphicsDevice.Viewport.Height / (int)(this.mLightMapSize);
+
+ this.mMap = new RenderTarget2D(GraphicsDevice, targetWidth, targetHeight, false, SurfaceFormat.Color, DepthFormat.Depth24Stencil8, 0, RenderTargetUsage.PlatformContents);
+ this.mMapBlur = new RenderTarget2D(GraphicsDevice, targetWidth, targetHeight, false, SurfaceFormat.Color, DepthFormat.Depth24Stencil8, 0, RenderTargetUsage.PlatformContents);
+ }
+
+ ///
+ /// Disposes of render targets
+ ///
+ private void DisposeRenderTargets()
+ {
+ KryptonEngine.TryDispose(this.mMap);
+ KryptonEngine.TryDispose(this.mMapBlur);
+ }
+
+ ///
+ /// Attempts to dispose of disposable objects, and assigns them a null value afterward
+ ///
+ ///
+ private static void TryDispose(IDisposable obj)
+ {
+ if (obj != null)
+ {
+ obj.Dispose();
+ obj = null;
+ }
+ }
+
+ ///
+ /// Draws the light map to the current render target
+ ///
+ /// N/A - Required
+ public override void Draw(GameTime gameTime)
+ {
+ this.LightMapPresent();
+ }
+
+ ///
+ /// Prepares the light map to be drawn (pre-render)
+ ///
+ public void LightMapPrepare()
+ {
+ // Prepare and set the matrix
+ var viewWidth = this.GraphicsDevice.ScissorRectangle.Width;
+ var viewHeight = this.GraphicsDevice.ScissorRectangle.Height;
+
+ // Prepare the matrix with optional settings and assign it to an effect parameter
+ Matrix lightMapMatrix = this.LightmapMatrixGet();
+ this.mEffect.Parameters["Matrix"].SetValue(lightMapMatrix);
+
+ // Obtain the original rendering states
+ var originalRenderTargets = this.GraphicsDevice.GetRenderTargets();
+
+ // Set and clear the target
+ this.GraphicsDevice.SetRenderTarget(this.mMap);
+ this.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.Stencil, this.mAmbientColor, 0, 1);
+
+ // Make sure we're culling the right way!
+ this.GraphicsDevice.RasterizerState = KryptonEngine.RasterizerStateGetFromCullMode(this.mCullMode);
+
+ // put the render target's size into a more friendly format
+ var targetSize = new Vector2(this.mMap.Width, this.mMap.Height);
+
+ // Render Light Maps
+ foreach (var light in this.mLights)
+ {
+ // Loop through each light within the view frustum
+ if (light.Bounds.Intersects(this.mBounds))
+ {
+ // Clear the stencil and set the scissor rect (because we're stretching geometry past the light's reach)
+ this.GraphicsDevice.Clear(ClearOptions.Stencil, Color.Black, 0, 1);
+ this.GraphicsDevice.ScissorRectangle = KryptonEngine.ScissorRectCreateForLight(light, lightMapMatrix, targetSize);
+
+ // Draw the light!
+ light.Draw(this.RenderHelper, this.mHulls);
+ }
+ }
+
+ if (this.mBluriness > 0)
+ {
+ // Blur the shadow map horizontally to the blur target
+ this.GraphicsDevice.SetRenderTarget(this.mMapBlur);
+ this.RenderHelper.BlurTextureToTarget(this.mMap, LightMapSize.Full, BlurTechnique.Horizontal, this.mBluriness);
+
+ // Blur the shadow map vertically back to the final map
+ this.GraphicsDevice.SetRenderTarget(this.mMap);
+ this.RenderHelper.BlurTextureToTarget(this.mMapBlur, LightMapSize.Full, BlurTechnique.Vertical, this.mBluriness);
+ }
+
+ // Reset to the original rendering states
+ this.GraphicsDevice.SetRenderTargets(originalRenderTargets);
+ }
+
+ ///
+ /// Returns the final, modified matrix used to render the lightmap.
+ ///
+ ///
+ private Matrix LightmapMatrixGet()
+ {
+ if (this.mSpriteBatchCompatabilityEnabled)
+ {
+ float xScale = (this.GraphicsDevice.Viewport.Width > 0) ? (1f / this.GraphicsDevice.Viewport.Width) : 0f;
+ float yScale = (this.GraphicsDevice.Viewport.Height > 0) ? (-1f / this.GraphicsDevice.Viewport.Height) : 0f;
+
+ // This is the default matrix used to render sprites via spritebatch
+ var matrixSpriteBatch = new Matrix()
+ {
+ M11 = xScale * 2f,
+ M22 = yScale * 2f,
+ M33 = 1f,
+ M44 = 1f,
+ M41 = -1f - xScale,
+ M42 = 1f - yScale,
+ };
+
+ // Return krypton's matrix, compensated for use with SpriteBatch
+ return this.mWVP * matrixSpriteBatch;
+ }
+ else
+ {
+ // Return krypton's matrix
+ return this.mWVP;
+ }
+ }
+
+ ///
+ /// Gets a pixel-space rectangle which contains the light passed in
+ ///
+ /// The light used to create the rectangle
+ /// the WorldViewProjection matrix being used to render
+ /// The rendertarget's size
+ ///
+ private static Rectangle ScissorRectCreateForLight(ILight2D light, Microsoft.Xna.Framework.Matrix matrix, Vector2 targetSize)
+ {
+ // This needs refining, but it works as is (I believe)
+ var lightBounds = light.Bounds;
+
+ var min = KryptonEngine.VectorToPixel(lightBounds.Min, matrix, targetSize);
+ var max = KryptonEngine.VectorToPixel(lightBounds.Max, matrix, targetSize);
+
+ var min2 = Vector2.Min(min, max);
+ var max2 = Vector2.Max(min, max);
+
+ min = Vector2.Clamp(min2, Vector2.Zero, targetSize);
+ max = Vector2.Clamp(max2, Vector2.Zero, targetSize);
+
+ return new Rectangle((int)(min.X), (int)(min.Y), (int)(max.X - min.X), (int)(max.Y - min.Y));
+ }
+
+ ///
+ /// Takes a screen-space vector and puts it in to pixel space
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static Vector2 VectorToPixel(Vector2 v, Matrix matrix, Vector2 targetSize)
+ {
+ Vector2.Transform(ref v, ref matrix, out v);
+
+ v.X = (1 + v.X) * (targetSize.X / 2f);
+ v.Y = (1 - v.Y) * (targetSize.Y / 2f);
+
+ return v;
+ }
+
+ ///
+ /// Takes a screen-space size vector and converts it to a pixel-space size vector
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static Vector2 ScaleToPixel(Vector2 v, Matrix matrix, Vector2 targetSize)
+ {
+ v.X *= matrix.M11 * (targetSize.X / 2f);
+ v.Y *= matrix.M22 * (targetSize.Y / 2f);
+
+ return v;
+ }
+
+ ///
+ /// Retrieves a rasterize state by using the cull mode as a lookup
+ ///
+ /// The cullmode used to lookup the rasterize state
+ ///
+ private static RasterizerState RasterizerStateGetFromCullMode(CullMode cullMode)
+ {
+ switch (cullMode)
+ {
+ case (CullMode.CullCounterClockwiseFace):
+ return RasterizerState.CullCounterClockwise;
+
+ case (CullMode.CullClockwiseFace):
+ return RasterizerState.CullClockwise;
+
+ default:
+ return RasterizerState.CullNone;
+ }
+ }
+
+ ///
+ /// Presents the light map to the current render target
+ ///
+ private void LightMapPresent()
+ {
+ RenderHelper.DrawTextureToTarget(this.mMap, this.mLightMapSize, BlendTechnique.Multiply);
+ }
+ }
+}
diff --git a/Krypton v2.0/Krypton/KryptonRenderHelper.cs b/Krypton v2.0/Krypton/KryptonRenderHelper.cs
new file mode 100755
index 0000000..ff8dcf9
--- /dev/null
+++ b/Krypton v2.0/Krypton/KryptonRenderHelper.cs
@@ -0,0 +1,476 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+
+using Krypton.Lights;
+
+namespace Krypton
+{
+ public enum BlendTechnique
+ {
+ Add = 1,
+ Multiply = 2,
+ };
+
+ public enum BlurTechnique
+ {
+ Horizontal = 1,
+ Vertical = 2,
+ };
+
+ public class KryptonRenderHelper
+ {
+ #region Static Unit Quad
+
+ private static VertexPositionTexture[] UnitQuad = new VertexPositionTexture[]
+ {
+ new VertexPositionTexture()
+ {
+ Position = new Vector3(-1, 1, 0),
+ TextureCoordinate = new Vector2(0, 0),
+ },
+ new VertexPositionTexture()
+ {
+ Position = new Vector3(1, 1, 0),
+ TextureCoordinate = new Vector2(1, 0),
+ },
+ new VertexPositionTexture()
+ {
+ Position = new Vector3(-1, -1, 0),
+ TextureCoordinate = new Vector2(0, 1),
+ },
+ new VertexPositionTexture()
+ {
+ Position = new Vector3(1, -1, 0),
+ TextureCoordinate = new Vector2(1, 1),
+ },
+ };
+
+ #endregion Static Unit Quad
+
+ private GraphicsDevice mGraphicsDevice;
+ private Effect mEffect;
+ private List mShadowHullVertices = new List();
+ private List mShadowHullIndicies = new List();
+
+ public GraphicsDevice GraphicsDevice
+ {
+ get { return this.mGraphicsDevice; }
+ }
+ public Effect Effect
+ {
+ get { return this.mEffect; }
+ }
+
+ public List ShadowHullVertices
+ {
+ get { return this.mShadowHullVertices; }
+ }
+ public List ShadowHullIndicies
+ {
+ get { return this.mShadowHullIndicies; }
+ }
+
+ public KryptonRenderHelper(GraphicsDevice graphicsDevice, Effect effect)
+ {
+ this.mGraphicsDevice = graphicsDevice;
+ this.mEffect = effect;
+ }
+
+ public void BufferAddShadowHull(ShadowHull hull)
+ {
+ // Why do we need all of these again? (hint: we don't)
+
+ Matrix vertexMatrix = Matrix.Identity;
+ Matrix normalMatrix = Matrix.Identity;
+
+ float cos, sin;
+
+ ShadowHullPoint point;
+ ShadowHullVertex hullVertex;
+
+ // Create the matrices (3X speed boost versus prior version)
+ cos = (float)Math.Cos(hull.Angle);
+ sin = (float)Math.Sin(hull.Angle);
+
+ // vertexMatrix = scale * rotation * translation;
+ vertexMatrix.M11 = hull.Scale.X * cos;
+ vertexMatrix.M12 = hull.Scale.X * sin;
+ vertexMatrix.M21 = hull.Scale.Y * -sin;
+ vertexMatrix.M22 = hull.Scale.Y * cos;
+ vertexMatrix.M41 = hull.Position.X;
+ vertexMatrix.M42 = hull.Position.Y;
+
+ // normalMatrix = scaleInv * rotation;
+ normalMatrix.M11 = (1f / hull.Scale.X) * cos;
+ normalMatrix.M12 = (1f / hull.Scale.X) * sin;
+ normalMatrix.M21 = (1f / hull.Scale.Y) * -sin;
+ normalMatrix.M22 = (1f / hull.Scale.Y) * cos;
+
+ // Where are we in the buffer?
+ var vertexCount = this.mShadowHullVertices.Count;
+
+ // Add the vertices to the buffer
+ for (int i = 0; i < hull.NumPoints; i++)
+ {
+
+ // Transform the vertices to screen coordinates
+ point = hull.Points[i];
+ Vector2.Transform(ref point.Position, ref vertexMatrix, out hullVertex.Position);
+ Vector2.TransformNormal(ref point.Normal, ref normalMatrix, out hullVertex.Normal);
+
+ hullVertex.Color = Color.Black;
+
+ this.mShadowHullVertices.Add(hullVertex); // could this be sped up... ?
+ }
+
+ //// Add the indicies to the buffer
+ foreach (int index in hull.Indicies)
+ {
+ mShadowHullIndicies.Add(vertexCount + index); // what about this? Add range?
+ }
+ }
+
+ public void DrawSquareQuad(Vector2 position, float rotation, float size, Color color)
+ {
+ size /= 2;
+
+ size = (float)Math.Sqrt(Math.Pow(size, 2) + Math.Pow(size, 2));
+
+ rotation += (float)Math.PI / 4;
+
+ var cos = (float)Math.Cos(rotation) * size;
+ var sin = (float)Math.Sin(rotation) * size;
+
+ var v1 = new Vector3(+cos, +sin, 0) + new Vector3(position, 0);
+ var v2 = new Vector3(-sin, +cos, 0) + new Vector3(position, 0);
+ var v3 = new Vector3(-cos, -sin, 0) + new Vector3(position, 0);
+ var v4 = new Vector3(+sin, -cos, 0) + new Vector3(position, 0);
+
+ var quad = new VertexPositionColorTexture[]
+ {
+ new VertexPositionColorTexture()
+ {
+ Position = v2,
+ Color = color,
+ TextureCoordinate = new Vector2(0,0),
+ },
+ new VertexPositionColorTexture()
+ {
+ Position = v1,
+ Color = color,
+ TextureCoordinate = new Vector2(1,0),
+ },
+ new VertexPositionColorTexture()
+ {
+ Position = v3,
+ Color = color,
+ TextureCoordinate = new Vector2(0,1),
+ },
+ new VertexPositionColorTexture()
+ {
+ Position = v4,
+ Color = color,
+ TextureCoordinate = new Vector2(1,1),
+ },
+ };
+
+ this.mGraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, quad, 0, 2);
+ }
+
+ public void DrawClippedFov(Vector2 position, float rotation, float size, Color color, float fov)
+ {
+ fov = MathHelper.Clamp(fov, 0, MathHelper.TwoPi);
+
+ if (fov == 0)
+ {
+ return;
+ }
+ else if (fov == MathHelper.TwoPi)
+ {
+ this.DrawSquareQuad(position, rotation, size, color);
+ return;
+ }
+ else
+ {
+ var ccw = ClampToBox(fov / 2);
+ var cw = ClampToBox(-fov / 2);
+
+ var ccwTex = new Vector2(ccw.X + 1, -ccw.Y + 1) / 2f;
+ var cwTex = new Vector2(cw.X + 1, -cw.Y + 1) / 2f;
+
+ VertexPositionColorTexture[] vertices;
+
+ #region Vertices
+ vertices = new VertexPositionColorTexture[]
+ {
+ new VertexPositionColorTexture()
+ {
+ Position = Vector3.Zero,
+ Color = color,
+ TextureCoordinate = new Vector2(0.5f, 0.5f),
+ },
+ new VertexPositionColorTexture()
+ {
+ Position = new Vector3(ccw,0),
+ Color = color,
+ TextureCoordinate = ccwTex
+ },
+ new VertexPositionColorTexture()
+ {
+ Position = new Vector3(-1, 1, 0),
+ Color = color,
+ TextureCoordinate = new Vector2(0, 0),
+ },
+ new VertexPositionColorTexture()
+ {
+ Position = new Vector3(1, 1, 0),
+ Color = color,
+ TextureCoordinate = new Vector2(1, 0),
+ },
+ new VertexPositionColorTexture()
+ {
+ Position = new Vector3(1, -1, 0),
+ Color = color,
+ TextureCoordinate = new Vector2(1, 1),
+ },
+ new VertexPositionColorTexture()
+ {
+ Position = new Vector3(-1, -1, 0),
+ Color = color,
+ TextureCoordinate = new Vector2(0, 1),
+ },
+ new VertexPositionColorTexture()
+ {
+ Position = new Vector3(cw, 0),
+ Color = color,
+ TextureCoordinate = cwTex,
+ },
+ };
+
+ var r = Matrix.CreateRotationZ(rotation) * Matrix.CreateScale(size / 2) * Matrix.CreateTranslation(new Vector3(position, 0));
+
+ for (int i = 0; i < vertices.Length; i++)
+ {
+ var vertex = vertices[i];
+
+ Vector3.Transform(ref vertex.Position, ref r, out vertex.Position);
+
+ vertices[i] = vertex;
+ }
+
+ #endregion Vertices
+
+ Int32[] indicies;
+
+ #region Indicies
+
+ if (fov <= MathHelper.Pi / 2)
+ {
+ indicies = new Int32[]
+ {
+ 0, 1, 6,
+ };
+ }
+ else if (fov <= 3 * MathHelper.Pi / 2)
+ {
+ indicies = new Int32[]
+ {
+ 0, 1, 3,
+ 0, 3, 4,
+ 0, 4, 6,
+ };
+ }
+ else
+ {
+ indicies = new Int32[]
+ {
+ 0, 1, 2,
+ 0, 2, 3,
+ 0, 3, 4,
+ 0, 4, 5,
+ 0, 5, 6,
+ };
+ }
+ #endregion Indicies
+
+ this.mGraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, vertices, 0, vertices.Length, indicies, 0, indicies.Length / 3);
+ }
+ }
+
+ public static Vector2 ClampToBox(float angle)
+ {
+ var x = Math.Cos(angle);
+ var y = Math.Sin(angle);
+ var absMax = Math.Max(Math.Abs(x), Math.Abs(y));
+
+ return new Vector2((float)(x / absMax), (float)(y / absMax));
+ }
+
+ public void BufferDraw()
+ {
+ if (this.mShadowHullIndicies.Count >= 3)
+ {
+ this.mGraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, this.mShadowHullVertices.ToArray(), 0, this.mShadowHullVertices.Count, this.mShadowHullIndicies.ToArray(), 0, this.mShadowHullIndicies.Count / 3);
+ }
+ }
+
+ public void DrawFullscreenQuad()
+ {
+ // Obtain the original rendering states
+ var originalRasterizerState = this.mGraphicsDevice.RasterizerState;
+
+ // Draw the quad
+ this.mEffect.CurrentTechnique = this.mEffect.Techniques["ScreenCopy"];
+ //this.mGraphicsDevice.RasterizerState = RasterizerState.CullNone;
+
+ this.mEffect.Parameters["TexelBias"].SetValue(new Vector2(0.5f / this.mGraphicsDevice.Viewport.Width, 0.5f / this.mGraphicsDevice.Viewport.Height));
+
+ foreach (var effectPass in this.mEffect.CurrentTechnique.Passes)
+ {
+ effectPass.Apply();
+ this.mGraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, KryptonRenderHelper.UnitQuad, 0, 2);
+ }
+
+ // Reset to the original rendering states
+ //this.mGraphicsDevice.RasterizerState = originalRasterizerState;
+ }
+
+ public void BlurTextureToTarget(Texture2D texture, LightMapSize mapSize, BlurTechnique blurTechnique, float bluriness)
+ {
+ // Get the pass to use
+ string passName = "";
+
+ switch (blurTechnique)
+ {
+ case (BlurTechnique.Horizontal):
+ this.mEffect.Parameters["BlurFactorU"].SetValue(1f / this.GraphicsDevice.PresentationParameters.BackBufferWidth);
+ passName = "HorizontalBlur";
+ break;
+
+ case (BlurTechnique.Vertical):
+ this.mEffect.Parameters["BlurFactorV"].SetValue(1f / this.mGraphicsDevice.PresentationParameters.BackBufferHeight);
+ passName = "VerticalBlur";
+ break;
+ }
+
+ var biasFactor = KryptonRenderHelper.BiasFactorFromLightMapSize(mapSize);
+
+ // Calculate the texel bias
+ Vector2 texelBias = new Vector2()
+ {
+ X = biasFactor / this.mGraphicsDevice.Viewport.Width,
+ Y = biasFactor / this.mGraphicsDevice.Viewport.Height,
+ };
+
+
+ this.mEffect.Parameters["Texture0"].SetValue(texture);
+ this.mEffect.Parameters["TexelBias"].SetValue(texelBias);
+ this.mEffect.Parameters["Bluriness"].SetValue(bluriness);
+ this.mEffect.CurrentTechnique = this.mEffect.Techniques["Blur"];
+
+ mEffect.CurrentTechnique.Passes[passName].Apply();
+ this.mGraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, KryptonRenderHelper.UnitQuad, 0, 2);
+ }
+
+ public void DrawTextureToTarget(Texture2D texture, LightMapSize mapSize, BlendTechnique blend)
+ {
+ // Get the technique to use
+ string techniqueName = "";
+
+ switch (blend)
+ {
+ case(BlendTechnique.Add):
+ techniqueName = "TextureToTarget_Add";
+ break;
+
+ case(BlendTechnique.Multiply):
+ techniqueName = "TextureToTarget_Multiply";
+ break;
+ }
+
+ var biasFactor = KryptonRenderHelper.BiasFactorFromLightMapSize(mapSize);
+
+ // Calculate the texel bias
+ Vector2 texelBias = new Vector2()
+ {
+ X = biasFactor / this.mGraphicsDevice.ScissorRectangle.Width,
+ Y = biasFactor / this.mGraphicsDevice.ScissorRectangle.Height,
+ };
+
+ this.mEffect.Parameters["Texture0"].SetValue(texture);
+ this.mEffect.Parameters["TexelBias"].SetValue(texelBias);
+ this.mEffect.CurrentTechnique = this.mEffect.Techniques[techniqueName];
+
+ // Draw the quad
+ foreach (var effectPass in this.mEffect.CurrentTechnique.Passes)
+ {
+ effectPass.Apply();
+ this.mGraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, KryptonRenderHelper.UnitQuad, 0, 2);
+ }
+ }
+
+ private static float BiasFactorFromLightMapSize(LightMapSize mapSize)
+ {
+ switch (mapSize)
+ {
+ case (LightMapSize.Full):
+ return 0.5f;
+
+ case (LightMapSize.Fourth):
+ return 0.6f;
+
+ case (LightMapSize.Eighth):
+ return 0.7f;
+
+ default:
+ return 0.0f;
+ }
+ }
+
+ public void BufferAddBoundOutline(Common.BoundingRect boundingRect)
+ {
+ var vertexCount = this.mShadowHullVertices.Count;
+
+ this.mShadowHullVertices.Add(new ShadowHullVertex()
+ {
+ Color = Color.Black,
+ Normal = Vector2.Zero,
+ Position = new Vector2(boundingRect.Left, boundingRect.Top)
+ });
+
+ this.mShadowHullVertices.Add(new ShadowHullVertex()
+ {
+ Color = Color.Black,
+ Normal = Vector2.Zero,
+ Position = new Vector2(boundingRect.Right, boundingRect.Top)
+ });
+
+ this.mShadowHullVertices.Add(new ShadowHullVertex()
+ {
+ Color = Color.Black,
+ Normal = Vector2.Zero,
+ Position = new Vector2(boundingRect.Right, boundingRect.Bottom)
+ });
+
+ this.mShadowHullVertices.Add(new ShadowHullVertex()
+ {
+ Color = Color.Black,
+ Normal = Vector2.Zero,
+ Position = new Vector2(boundingRect.Left, boundingRect.Bottom)
+ });
+
+ this.mShadowHullIndicies.Add(vertexCount + 0);
+ this.mShadowHullIndicies.Add(vertexCount + 1);
+ this.mShadowHullIndicies.Add(vertexCount + 2);
+
+ this.mShadowHullIndicies.Add(vertexCount + 0);
+ this.mShadowHullIndicies.Add(vertexCount + 2);
+ this.mShadowHullIndicies.Add(vertexCount + 3);
+ }
+ }
+}
diff --git a/Krypton v2.0/Krypton/LightTextureBuilder.cs b/Krypton v2.0/Krypton/LightTextureBuilder.cs
new file mode 100755
index 0000000..dae80a9
--- /dev/null
+++ b/Krypton v2.0/Krypton/LightTextureBuilder.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+
+namespace Krypton
+{
+ public static class LightTextureBuilder
+ {
+ ///
+ /// Create a Point Light based on a size.
+ ///
+ /// Your game's GraphicsDevice
+ /// Maximum Size
+ /// Light Texture
+ public static Texture2D CreatePointLight(GraphicsDevice device, int size)
+ {
+ return CreateConicLight(device, size, MathHelper.TwoPi, 0);
+ }
+
+ ///
+ /// Create a Conic Light based on the size, and field of view.
+ ///
+ /// Your game's GraphicsDevice
+ /// Maximum Size
+ /// Maximum Field of View
+ /// Light Texture
+ public static Texture2D CreateConicLight(GraphicsDevice device, int size, float FOV)
+ {
+ return CreateConicLight(device, size, FOV, 0);
+ }
+
+ ///
+ /// Create a Conic Light based on the size, field of view, and near plane distance.
+ ///
+ /// Your game's GraphicsDevice
+ /// Maximum size
+ /// Maximum Field of View
+ /// Prevents texture from being drawn at this plane distance, originating from the center of light
+ /// Light Texture
+ public static Texture2D CreateConicLight(GraphicsDevice device, int size, float FOV, float nearPlaneDistance)
+ {
+ /*if (!IsPowerOfTwo(size))
+ throw new Exception("The size must be a power of 2");*/
+ float[,] Data = new float[size, size];
+
+ float center = size / 2;
+
+ FOV = FOV / 2;
+
+ for (int x = 0; x < size; x++)
+ for (int y = 0; y < size; y++)
+ {
+ float Distance = Vector2.Distance(new Vector2(x, y), new Vector2(center));
+
+ Vector2 Difference = new Vector2(x, y) - new Vector2(center);
+ float Angle = (float)Math.Atan2(Difference.Y, Difference.X);
+
+ if (Distance <= center && Distance >= nearPlaneDistance && Math.Abs(Angle) <= FOV)
+ Data[x, y] = (center - Distance) / center;
+ else
+ Data[x, y] = 0;
+ }
+
+ Texture2D tex = new Texture2D(device, size, size);
+
+ Color[] Data1D = new Color[size * size];
+ for (int x = 0; x < size; x++)
+ for (int y = 0; y < size; y++)
+ Data1D[x + y * size] = new Color(new Vector3(Data[x, y]));
+
+ tex.SetData(Data1D);
+
+ return tex;
+ }
+
+ ///
+ /// Math helper to determine if integer is a power of two
+ ///
+ /// Integer value
+ private static bool IsPowerOfTwo(int x)
+ {
+ return (x & (x - 1)) == 0;
+ }
+ }
+}
diff --git a/Krypton v2.0/Krypton/Lights/ILight2D.cs b/Krypton v2.0/Krypton/Lights/ILight2D.cs
new file mode 100755
index 0000000..4e67e34
--- /dev/null
+++ b/Krypton v2.0/Krypton/Lights/ILight2D.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Xna.Framework;
+
+using Krypton.Common;
+
+namespace Krypton.Lights
+{
+ public interface ILight2D
+ {
+ BoundingRect Bounds { get; }
+
+ void Draw(KryptonRenderHelper renderHelper, List hulls);
+ }
+}
diff --git a/Krypton v2.0/Krypton/Lights/Light2D.cs b/Krypton v2.0/Krypton/Lights/Light2D.cs
new file mode 100755
index 0000000..b0bcdb1
--- /dev/null
+++ b/Krypton v2.0/Krypton/Lights/Light2D.cs
@@ -0,0 +1,192 @@
+using System;
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+
+using Microsoft.Xna.Framework.Input;
+
+using Krypton.Common;
+
+namespace Krypton.Lights
+{
+ public class Light2D : ILight2D
+ {
+ private bool mIsOn = true;
+ private Vector2 mPosition = Vector2.Zero;
+ private float mAngle = 0;
+ private Texture2D mTexture = null;
+ private Color mColor = Color.White;
+ private float mRange = 1;
+ private float mFov = MathHelper.TwoPi;
+ private float mIntensity = 1;
+
+ #region Parameters
+
+ ///
+ /// The light's position
+ ///
+ public Vector2 Position
+ {
+ get { return this.mPosition; }
+ set { this.mPosition = value; }
+ }
+
+ ///
+ /// The X coordinate of the light's position
+ ///
+ public float X
+ {
+ get { return this.mPosition.X; }
+ set { this.mPosition.X = value; }
+ }
+
+ ///
+ /// The Y coordinate of the light's position
+ ///
+ public float Y
+ {
+ get { return this.mPosition.Y; }
+ set { this.mPosition.Y = value; }
+ }
+
+ ///
+ /// The light's angle
+ ///
+ public float Angle
+ {
+ get { return this.mAngle; }
+ set { this.mAngle = value; }
+ }
+
+ ///
+ /// The texture used as the base light map, from which shadows will be subtracted
+ ///
+ public Texture2D Texture
+ {
+ get { return this.mTexture; }
+ set { this.mTexture = value; }
+ }
+
+ ///
+ /// The color used to tint the light's texture
+ ///
+ public Color Color
+ {
+ get { return this.mColor; }
+ set { this.mColor = value; }
+ }
+
+ ///
+ /// The light's maximum radius (or "half width", if you will)
+ ///
+ public float Range
+ {
+ get { return this.mRange; }
+ set { this.mRange = value; }
+ }
+
+ ///
+ /// Gets or sets the light's field of view. This value determines the angles at which the light will cease to draw
+ ///
+ public float Fov
+ {
+ get { return this.mFov; }
+ set
+ {
+ this.mFov = MathHelper.Clamp(value, 0, MathHelper.TwoPi);
+ }
+ }
+
+ ///
+ /// Gets or sets the light's intensity. Think pixel = (tex * color) ^ (1 / intensity)
+ ///
+ public float Intensity
+ {
+ get { return this.mIntensity; }
+ set { this.mIntensity = MathHelper.Clamp(value, 0.01f, 3f); }
+ }
+
+ #endregion Parameters
+
+ ///
+ /// Gets or sets a value indicating weither or not to draw the light
+ ///
+ public bool IsOn
+ {
+ get { return this.mIsOn; }
+ set { this.mIsOn = value; }
+ }
+
+ ///
+ /// Draws shadows from the light's position outward
+ ///
+ /// A render helper for drawing shadows
+ /// The shadow hulls used to draw shadows
+ public void Draw(KryptonRenderHelper helper, List hulls)
+ {
+ // Draw the light only if it's on
+ if (!this.mIsOn)
+ return;
+
+ // Make sure we only render the following hulls
+ helper.ShadowHullVertices.Clear();
+ helper.ShadowHullIndicies.Clear();
+
+ // Loop through each hull
+ foreach (ShadowHull hull in hulls)
+ {
+ //if(hull.Bounds.Intersects(this.Bounds))
+ // Add the hulls to the buffer only if they are within the light's range
+ if (hull.Visible && Light2D.IsInRange(hull.Position - this.Position, hull.MaxRadius * Math.Max(hull.Scale.X, hull.Scale.Y) + this.Range))
+ {
+ helper.BufferAddShadowHull(hull);
+ }
+ }
+
+ var shadowEffect = helper.Effect.Techniques["PointLight_Shadow_Fast"];
+ helper.Effect.CurrentTechnique = shadowEffect;
+ // Set the effect parameters
+ helper.Effect.Parameters["LightPosition"].SetValue(this.mPosition);
+ helper.Effect.Parameters["Texture0"].SetValue(this.mTexture);
+ helper.Effect.Parameters["LightIntensityFactor"].SetValue(1 / (this.mIntensity * this.mIntensity));
+
+ shadowEffect.Passes["ShadowStencil"].Apply();
+ helper.BufferDraw();
+
+ shadowEffect.Passes["Light"].Apply();
+ helper.DrawClippedFov(this.mPosition, this.mAngle, this.mRange * 2, this.mColor, this.mFov);
+ }
+
+ ///
+ /// Determines if a vector's length is less than a specified value
+ ///
+ /// Offset
+ /// Distance
+ ///
+ private static bool IsInRange(Vector2 offset, float dist)
+ {
+ if (offset.X * offset.X + offset.Y * offset.Y < dist * dist)
+ return true;
+
+ return false;
+ }
+
+ ///
+ /// Gets the world-space bounds which contain the light
+ ///
+ public BoundingRect Bounds
+ {
+ get
+ {
+ BoundingRect rect;
+
+ rect.Min.X = this.mPosition.X - this.mRange;
+ rect.Min.Y = this.mPosition.Y - this.mRange;
+ rect.Max.X = this.mPosition.X + this.mRange;
+ rect.Max.Y = this.mPosition.Y + this.mRange;
+
+ return rect;
+ }
+ }
+ }
+}
diff --git a/Krypton v2.0/Krypton/Properties/AssemblyInfo.cs b/Krypton v2.0/Krypton/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..bfb5383
--- /dev/null
+++ b/Krypton v2.0/Krypton/Properties/AssemblyInfo.cs
@@ -0,0 +1,34 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Krypton")]
+[assembly: AssemblyProduct("Krypton")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type. Only Windows
+// assemblies support COM.
+[assembly: ComVisible(false)]
+
+// On Windows, the following GUID is for the ID of the typelib if this
+// project is exposed to COM. On other platforms, it unique identifies the
+// title storage container when deploying this assembly to the device.
+[assembly: Guid("0ce98116-fee5-4948-bdc1-edab3ed0d43e")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("1.0.0.0")]
diff --git a/Krypton v2.0/Krypton/ShadowHull.cs b/Krypton v2.0/Krypton/ShadowHull.cs
new file mode 100755
index 0000000..bb78128
--- /dev/null
+++ b/Krypton v2.0/Krypton/ShadowHull.cs
@@ -0,0 +1,241 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using Krypton.Common;
+
+namespace Krypton
+{
+ ///
+ /// A hull used for casting shadows from a light source
+ ///
+ public class ShadowHull
+ {
+ #region Orientation
+
+ ///
+ /// The position of the shadow hull
+ ///
+ public Vector2 Position;
+
+ ///
+ /// The angle of the shadow hull
+ ///
+ public float Angle;
+
+ #endregion
+
+ #region Shape
+
+ ///
+ /// The maximum radius in which all of the shadow hull's vertices are contained, originating from the hull's position
+ ///
+ public float MaxRadius;
+
+ ///
+ /// The vertices comprising the shadow hull
+ ///
+ public ShadowHullPoint[] Points;
+
+ ///
+ /// The number of vertices comprising the shadow hull
+ ///
+ public int NumPoints;
+
+ ///
+ /// The indicies used to render the shadow hull
+ ///
+ public Int32[] Indicies;
+
+ ///
+ /// The number of indicies used to render the shadow hull
+ ///
+ public int NumIndicies;
+
+ ///
+ /// A value indicating if the hull should cast a shadow
+ ///
+ public bool Visible = true;
+
+ ///
+ /// A value indicating how much to stretch the hull
+ ///
+ public Vector2 Scale = Vector2.One;
+
+ #endregion
+
+ private ShadowHull(){}
+
+ #region Factory Methods
+
+ ///
+ /// Creates a rectangular shadow hull
+ ///
+ /// The dimensions of the rectangle
+ /// A rectangular shadow hull
+ public static ShadowHull CreateRectangle(Vector2 size)
+ {
+ ShadowHull hull = new ShadowHull();
+
+ size *= 0.5f;
+
+ hull.MaxRadius = (float)Math.Sqrt(size.X * size.X + size.Y * size.Y);
+
+ hull.NumPoints = 4 * 2;
+ var numTris = hull.NumPoints - 2;
+ hull.NumIndicies = numTris * 3;
+
+ hull.Points = new ShadowHullPoint[hull.NumPoints];
+ hull.Indicies = new Int32[hull.NumIndicies];
+
+ // Vertex position
+ var posTR = new Vector2(+size.X, +size.Y);
+ var posBR = new Vector2(+size.X, -size.Y);
+ var posBL = new Vector2(-size.X, -size.Y);
+ var posTL = new Vector2(-size.X, +size.Y);
+
+ // Right
+ hull.Points[0] = new ShadowHullPoint(posTR, Vector2.UnitX);
+ hull.Points[1] = new ShadowHullPoint(posBR, Vector2.UnitX);
+
+ // Bottom
+ hull.Points[2] = new ShadowHullPoint(posBR, -Vector2.UnitY);
+ hull.Points[3] = new ShadowHullPoint(posBL, -Vector2.UnitY);
+
+ // Left
+ hull.Points[4] = new ShadowHullPoint(posBL, -Vector2.UnitX);
+ hull.Points[5] = new ShadowHullPoint(posTL, -Vector2.UnitX);
+
+ // Top
+ hull.Points[6] = new ShadowHullPoint(posTL, Vector2.UnitY);
+ hull.Points[7] = new ShadowHullPoint(posTR, Vector2.UnitY);
+
+ // Create tris
+ for (int i = 0; i < numTris; i++)
+ {
+ hull.Indicies[i * 3 + 0] = 0;
+ hull.Indicies[i * 3 + 1] = i + 1;
+ hull.Indicies[i * 3 + 2] = i + 2;
+ }
+
+ return hull;
+ }
+
+ ///
+ /// Creates a circular shadow hull
+ ///
+ /// radius of the circle
+ /// number of sides the circle will be comprised of
+ /// A circular shadow hull
+ public static ShadowHull CreateCircle(float radius, int sides)
+ {
+ // Validate input
+ if (sides < 3) { throw new ArgumentException("Shadow hull must have at least 3 sides."); }
+
+ ShadowHull hull = new ShadowHull();
+
+ hull.MaxRadius = radius;
+
+ // Calculate number of sides
+ hull.NumPoints = sides * 2;
+ var numTris = hull.NumPoints - 2;
+ hull.NumIndicies = numTris * 3;
+
+ hull.Points = new ShadowHullPoint[hull.NumPoints];
+ hull.Indicies = new Int32[hull.NumIndicies];
+
+ var angle = (float)(-Math.PI * 2) / sides; // XNA Renders Clockwise
+ var angleOffset = angle / 2;
+
+ for (int i = 0; i < sides; i++)
+ {
+ // Create vertices
+ var v1 = new ShadowHullPoint();
+ var v2 = new ShadowHullPoint();
+
+ // Vertex Position
+ v1.Position.X = (float)Math.Cos(angle * i) * radius;
+ v1.Position.Y = (float)Math.Sin(angle * i) * radius;
+
+ v2.Position.X = (float)Math.Cos(angle * (i + 1)) * radius;
+ v2.Position.Y = (float)Math.Sin(angle * (i + 1)) * radius;
+
+ // Vertex Normal
+ v1.Normal.X = (float)Math.Cos(angle * i + angleOffset);
+ v1.Normal.Y = (float)Math.Sin(angle * i + angleOffset);
+
+ v2.Normal.X = (float)Math.Cos(angle * i + angleOffset);
+ v2.Normal.Y = (float)Math.Sin(angle * i + angleOffset);
+
+ // Copy vertices
+ hull.Points[i * 2 + 0] = v1;
+ hull.Points[i * 2 + 1] = v2;
+ }
+
+ for (int i = 0; i < numTris; i++)
+ {
+ hull.Indicies[i * 3 + 0] = 0;
+ hull.Indicies[i * 3 + 1] = (Int32)(i + 1);
+ hull.Indicies[i * 3 + 2] = (Int32)(i + 2);
+ }
+
+ return hull;
+ }
+
+ ///
+ /// Creates a custom shadow hull based on a series of vertices
+ ///
+ /// The points which the shadow hull will be comprised of
+ /// A custom shadow hulll
+ public static ShadowHull CreateConvex(ref Vector2[] points)
+ {
+ // Validate input
+ if (points == null) { throw new ArgumentNullException("Points cannot be null."); }
+ if (points.Length < 3) { throw new ArgumentException("Need at least 3 points to create shadow hull."); }
+
+ var numPoints = points.Length;
+
+ ShadowHull hull = new ShadowHull();
+
+ hull.NumPoints = numPoints * 2;
+ var numTris = hull.NumPoints - 2;
+ hull.NumIndicies = numTris * 3;
+
+ hull.Points = new ShadowHullPoint[hull.NumPoints];
+ hull.Indicies = new Int32[hull.NumIndicies];
+
+ Vector2 pointMin = points[0];
+ Vector2 pointMax = points[0];
+
+ for (int i = 0; i < numPoints; i++)
+ {
+ var p1 = points[(i + 0) % numPoints];
+ var p2 = points[(i + 1) % numPoints];
+
+ hull.MaxRadius = Math.Max(hull.MaxRadius, p1.Length());
+
+ var line = p2 - p1;
+
+ var normal = new Vector2(-line.Y, +line.X);
+
+ normal.Normalize();
+
+ hull.Points[i * 2 + 0] = new ShadowHullPoint(p1, normal);
+ hull.Points[i * 2 + 1] = new ShadowHullPoint(p2, normal);
+ }
+
+ for (Int32 i = 0; i < numTris; i++)
+ {
+ hull.Indicies[i * 3 + 0] = 0;
+ hull.Indicies[i * 3 + 1] = (Int32)(i + 1);
+ hull.Indicies[i * 3 + 2] = (Int32)(i + 2);
+ }
+
+ return hull;
+ }
+
+ #endregion
+ }
+}
diff --git a/Krypton v2.0/Krypton/ShadowHullPoint.cs b/Krypton v2.0/Krypton/ShadowHullPoint.cs
new file mode 100755
index 0000000..14e959f
--- /dev/null
+++ b/Krypton v2.0/Krypton/ShadowHullPoint.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Microsoft.Xna.Framework;
+
+namespace Krypton
+{
+ ///
+ /// A two dimensional point with normal
+ ///
+ public struct ShadowHullPoint
+ {
+ ///
+ /// Creates a new Shadow Hull Point
+ ///
+ /// The position of the point
+ /// The normal of the side which the point helps represent
+ public ShadowHullPoint(Vector2 position, Vector2 normal)
+ {
+ this.Position = position;
+ this.Normal = normal;
+ }
+
+ ///
+ /// The position of the point
+ ///
+ public Vector2 Position;
+
+ ///
+ /// The normal of the side of the shadow hull of which the point helps represent
+ ///
+ public Vector2 Normal;
+ }
+}
diff --git a/Krypton v2.0/Krypton/ShadowHullVertex.cs b/Krypton v2.0/Krypton/ShadowHullVertex.cs
new file mode 100755
index 0000000..85978fa
--- /dev/null
+++ b/Krypton v2.0/Krypton/ShadowHullVertex.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+
+namespace Krypton
+{
+ public struct ShadowHullVertex : IVertexType
+ {
+ ///
+ /// The position of the vertex
+ ///
+ public Vector2 Position;
+
+ ///
+ /// The normal of the vertex
+ ///
+ public Vector2 Normal;
+
+ ///
+ /// The color of vertex
+ ///
+ public Color Color;
+
+ private static readonly VertexDeclaration mVertexDeclaration;
+
+ ///
+ ///
+ ///
+ public VertexDeclaration VertexDeclaration { get { return ShadowHullVertex.mVertexDeclaration; } }
+
+ static ShadowHullVertex()
+ {
+ VertexElement[] elements = new VertexElement[]
+ {
+ new VertexElement(0, VertexElementFormat.Vector2, VertexElementUsage.Position, 0),
+ new VertexElement(8, VertexElementFormat.Vector2, VertexElementUsage.Normal,0),
+ new VertexElement(16, VertexElementFormat.Color, VertexElementUsage.Color,0),
+ };
+
+ mVertexDeclaration = new VertexDeclaration(elements);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ShadowHullVertex(Vector2 position, Vector2 normal, Color color)
+ {
+ this.Position = position;
+ this.Normal = normal;
+ this.Color = color;
+ }
+ }
+}
diff --git a/Krypton v2.0/KryptonTestbed/KryptonTestbed/Game.ico b/Krypton v2.0/KryptonTestbed/KryptonTestbed/Game.ico
new file mode 100755
index 0000000..8cff41e
Binary files /dev/null and b/Krypton v2.0/KryptonTestbed/KryptonTestbed/Game.ico differ
diff --git a/Krypton v2.0/KryptonTestbed/KryptonTestbed/GameKryptonDemo.cs b/Krypton v2.0/KryptonTestbed/KryptonTestbed/GameKryptonDemo.cs
new file mode 100755
index 0000000..257489f
--- /dev/null
+++ b/Krypton v2.0/KryptonTestbed/KryptonTestbed/GameKryptonDemo.cs
@@ -0,0 +1,245 @@
+using System;
+using System.Collections.Generic;
+//using System.Linq;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Audio;
+using Microsoft.Xna.Framework.Content;
+using Microsoft.Xna.Framework.GamerServices;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+using Microsoft.Xna.Framework.Media;
+
+using Krypton;
+using Krypton.Lights;
+
+namespace KryptonTestbed
+{
+ ///
+ /// This is the main type for your game
+ ///
+ public class KryptonDemoGame : Microsoft.Xna.Framework.Game
+ {
+ GraphicsDeviceManager graphics;
+
+ KryptonEngine krypton;
+
+ private Texture2D mLightTexture;
+ private int mNumLights = 50;
+ private int mNumHorzontalHulls = 15;
+ private int mNumVerticalHulls = 15;
+
+ private float mVerticalUnits = 50;
+
+ Random mRandom = new Random();
+
+ public KryptonDemoGame()
+ {
+ // Setup the graphics device manager with some default settings
+ this.graphics = new GraphicsDeviceManager(this);
+ this.graphics.PreferredBackBufferWidth = 1280;
+ this.graphics.PreferredBackBufferHeight = 720;
+
+ // Allow the window to be resized (to demonstrate render target recreation)
+ this.Window.AllowUserResizing = true;
+
+ // Setup the content manager with some default settings
+ this.Content.RootDirectory = "Content";
+
+ // Create Krypton
+ this.krypton = new KryptonEngine(this, "KryptonEffect");
+
+ // As a side note, you may want Krypton to be used as a GameComponent.
+ // To do this, you would simply add the following line of code and remove the Initialize and Draw function of krypton below:
+ // this.Components.Add(this.krypton);
+ }
+
+ protected override void Initialize()
+ {
+ // Make sure to initialize krpyton, unless it has been added to the Game's list of Components
+ this.krypton.Initialize();
+
+ base.Initialize();
+ }
+
+ protected override void LoadContent()
+ {
+ // Create a new simple point light texture to use for the lights
+ this.mLightTexture = LightTextureBuilder.CreatePointLight(this.GraphicsDevice, 512);
+
+ // Create some lights and hulls
+ this.CreateLights(mLightTexture, this.mNumLights);
+ this.CreateHulls(this.mNumHorzontalHulls, this.mNumVerticalHulls);
+ }
+
+ private void CreateLights(Texture2D texture, int count)
+ {
+ // Make some random lights!
+ for (int i = 0; i < count; i++)
+ {
+ byte r = (byte)(this.mRandom.Next(255 - 64) + 64);
+ byte g = (byte)(this.mRandom.Next(255 - 64) + 64);
+ byte b = (byte)(this.mRandom.Next(255 - 64) + 64);
+
+ Light2D light = new Light2D()
+ {
+ Texture = texture,
+ Range = (float)(this.mRandom.NextDouble() * 5 + 1),
+ Color = new Color(r,g,b),
+ //Intensity = (float)(this.mRandom.NextDouble() * 0.25 + 0.75),
+ Intensity = 1f,
+ Angle = MathHelper.TwoPi * (float)this.mRandom.NextDouble(),
+ X = (float)(this.mRandom.NextDouble() * 50 - 25),
+ Y = (float)(this.mRandom.NextDouble() * 50 - 25),
+ };
+
+ // Here we set the light's field of view
+ if (i % 2 == 0)
+ {
+ light.Fov = MathHelper.PiOver2 * (float)(this.mRandom.NextDouble() * 0.75 + 0.25);
+ }
+
+ this.krypton.Lights.Add(light);
+ }
+ }
+
+ private void CreateHulls(int x, int y)
+ {
+ float w = 50;
+ float h = 50;
+
+ // Make lines of lines of hulls!
+ for (int j = 0; j < y; j++)
+ {
+ // Make lines of hulls!
+ for (int i = 0; i < x; i++)
+ {
+ var posX = ((i * w) / x) - w / 2 + (j % 2 == 0 ? w / x / 2 : 0);
+ var posY = ((j * h) / y) - h / 2 + (i % 2 == 0 ? h / y / 4 : 0);
+
+ var hull = ShadowHull.CreateRectangle(Vector2.One);
+ hull.Position.X = posX;
+ hull.Position.Y = posY;
+ hull.Scale.X = (float)(this.mRandom.NextDouble() * 0.75f + 0.25f);
+ hull.Scale.Y = (float)(this.mRandom.NextDouble() * 0.75f + 0.25f);
+
+ krypton.Hulls.Add(hull);
+ }
+ }
+ }
+
+ protected override void UnloadContent()
+ {
+ // Not sure if anything actually NEEDS to go here, as the game exits immediately upon unloading content. Please advise if you think this is bad :)
+ }
+
+ protected override void Update(GameTime gameTime)
+ {
+ // Make sure the user doesn't want to quit (but why would they?)
+ if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Escape))
+ this.Exit();
+
+ // make it much simpler to deal with the time :)
+ var t = (float)gameTime.ElapsedGameTime.TotalSeconds;
+
+ var speed = 5;
+
+ // Allow for randomization of lights and hulls, to demonstrait that each hull and light is individually rendered
+ if (Keyboard.GetState().IsKeyDown(Keys.R))
+ {
+ // randomize lights
+ foreach (Light2D light in this.krypton.Lights)
+ {
+ light.Position += Vector2.UnitY * (float)(this.mRandom.NextDouble() * 2 - 1) * t * speed;
+ light.Position += Vector2.UnitX * (float)(this.mRandom.NextDouble() * 2 - 1) * t * speed;
+ light.Angle -= MathHelper.TwoPi * (float)(this.mRandom.NextDouble() * 2 - 1) * t * speed;
+ }
+
+ // randomize hulls
+ foreach (var hull in this.krypton.Hulls)
+ {
+ hull.Position += Vector2.UnitY * (float)(this.mRandom.NextDouble() * 2 - 1) * t * speed;
+ hull.Position += Vector2.UnitX * (float)(this.mRandom.NextDouble() * 2 - 1) * t * speed;
+ hull.Angle -= MathHelper.TwoPi * (float)(this.mRandom.NextDouble() * 2 - 1) * t * speed;
+ }
+ }
+
+ base.Update(gameTime);
+ }
+
+ protected override void Draw(GameTime gameTime)
+ {
+ // Create a world view projection matrix to use with krypton
+ Matrix world = Matrix.Identity;
+ Matrix view = Matrix.CreateTranslation(new Vector3(0, 0, 0) * -1f);
+ Matrix projection = Matrix.CreateOrthographic(this.mVerticalUnits * this.GraphicsDevice.Viewport.AspectRatio, this.mVerticalUnits, 0, 1);
+
+ // Assign the matrix and pre-render the lightmap.
+ // Make sure not to change the position of any lights or shadow hulls after this call, as it won't take effect till the next frame!
+ this.krypton.Matrix = world * view * projection;
+ this.krypton.Bluriness = 3;
+ this.krypton.LightMapPrepare();
+
+ // Make sure we clear the backbuffer *after* Krypton is done pre-rendering
+ this.GraphicsDevice.Clear(Color.White);
+
+ // ----- DRAW STUFF HERE ----- //
+ // By drawing here, you ensure that your scene is properly lit by krypton.
+ // Drawing after KryptonEngine.Draw will cause you objects to be drawn on top of the lightmap (can be useful, fyi)
+ // ----- DRAW STUFF HERE ----- //
+
+ // Draw krypton (This can be omited if krypton is in the Component list. It will simply draw krypton when base.Draw is called
+ this.krypton.Draw(gameTime);
+
+ // Draw the shadow hulls as-is (no shadow stretching) in pure white on top of the shadows
+ // You can omit this line if you want to see what the light-map looks like :)
+ this.DebugDraw();
+
+ base.Draw(gameTime);
+ }
+
+ private void DebugDraw()
+ {
+ this.krypton.RenderHelper.Effect.CurrentTechnique = this.krypton.RenderHelper.Effect.Techniques["DebugDraw"];
+ this.GraphicsDevice.RasterizerState = new RasterizerState()
+ {
+ CullMode = CullMode.None,
+ FillMode = FillMode.WireFrame,
+ };
+ if (Keyboard.GetState().IsKeyDown(Keys.H))
+ {
+ // Clear the helpers vertices
+ this.krypton.RenderHelper.ShadowHullVertices.Clear();
+ this.krypton.RenderHelper.ShadowHullIndicies.Clear();
+
+ foreach (var hull in krypton.Hulls)
+ {
+ this.krypton.RenderHelper.BufferAddShadowHull(hull);
+ }
+
+
+ foreach (var effectPass in krypton.RenderHelper.Effect.CurrentTechnique.Passes)
+ {
+ effectPass.Apply();
+ this.krypton.RenderHelper.BufferDraw();
+ }
+ }
+
+ if (Keyboard.GetState().IsKeyDown(Keys.L))
+ {
+ this.krypton.RenderHelper.ShadowHullVertices.Clear();
+ this.krypton.RenderHelper.ShadowHullIndicies.Clear();
+
+ foreach (Light2D light in krypton.Lights)
+ {
+ this.krypton.RenderHelper.BufferAddBoundOutline(light.Bounds);
+ }
+
+ foreach (var effectPass in krypton.RenderHelper.Effect.CurrentTechnique.Passes)
+ {
+ effectPass.Apply();
+ this.krypton.RenderHelper.BufferDraw();
+ }
+ }
+ }
+ }
+}
diff --git a/Krypton v2.0/KryptonTestbed/KryptonTestbed/GameThumbnail.png b/Krypton v2.0/KryptonTestbed/KryptonTestbed/GameThumbnail.png
new file mode 100755
index 0000000..462311a
Binary files /dev/null and b/Krypton v2.0/KryptonTestbed/KryptonTestbed/GameThumbnail.png differ
diff --git a/Krypton v2.0/KryptonTestbed/KryptonTestbed/KryptonTestbed.csproj b/Krypton v2.0/KryptonTestbed/KryptonTestbed/KryptonTestbed.csproj
new file mode 100755
index 0000000..78f58f8
--- /dev/null
+++ b/Krypton v2.0/KryptonTestbed/KryptonTestbed/KryptonTestbed.csproj
@@ -0,0 +1,153 @@
+
+
+
+ {E9787BEE-7290-4C74-B919-79DC70AABE87}
+ {6D335F3A-9D43-41b4-9D22-F6F17C4BE596};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Debug
+ x86
+ WinExe
+ Properties
+ KryptonTestbed
+ KryptonTestbed
+ v4.0
+ Client
+ v4.0
+ Windows
+ HiDef
+ 04e8736f-6d19-442f-95e4-08f9b783d054
+ Game
+ Game.ico
+ GameThumbnail.png
+
+
+
+
+
+
+
+
+ publish\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 0
+ 1.0.0.%2a
+ false
+ false
+ true
+
+
+ true
+ full
+ false
+ bin\x86\Debug
+ DEBUG;TRACE;WINDOWS
+ prompt
+ 4
+ true
+ false
+ x86
+ false
+
+
+ pdbonly
+ true
+ bin\x86\Release
+ TRACE;WINDOWS
+ prompt
+ 4
+ true
+ false
+ x86
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}
+ Krypton
+
+
+ KryptonTestbedContent
+ Content
+
+
+
+
+ False
+ Microsoft .NET Framework 4 Client Profile %28x86 and x64%29
+ true
+
+
+ False
+ .NET Framework 3.5 SP1 Client Profile
+ false
+
+
+ False
+ .NET Framework 3.5 SP1
+ false
+
+
+ False
+ Windows Installer 3.1
+ true
+
+
+ False
+ Microsoft XNA Framework Redistributable 4.0
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Krypton v2.0/KryptonTestbed/KryptonTestbed/Program.cs b/Krypton v2.0/KryptonTestbed/KryptonTestbed/Program.cs
new file mode 100755
index 0000000..bbc294f
--- /dev/null
+++ b/Krypton v2.0/KryptonTestbed/KryptonTestbed/Program.cs
@@ -0,0 +1,21 @@
+using System;
+
+namespace KryptonTestbed
+{
+#if WINDOWS || XBOX
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ static void Main(string[] args)
+ {
+ using (KryptonDemoGame game = new KryptonDemoGame())
+ {
+ game.Run();
+ }
+ }
+ }
+#endif
+}
+
diff --git a/Krypton v2.0/KryptonTestbed/KryptonTestbed/Properties/AssemblyInfo.cs b/Krypton v2.0/KryptonTestbed/KryptonTestbed/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..a9780bc
--- /dev/null
+++ b/Krypton v2.0/KryptonTestbed/KryptonTestbed/Properties/AssemblyInfo.cs
@@ -0,0 +1,34 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("KryptonTestbed")]
+[assembly: AssemblyProduct("KryptonTestbed")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type. Only Windows
+// assemblies support COM.
+[assembly: ComVisible(false)]
+
+// On Windows, the following GUID is for the ID of the typelib if this
+// project is exposed to COM. On other platforms, it unique identifies the
+// title storage container when deploying this assembly to the device.
+[assembly: Guid("44537967-0d21-441c-bf8b-9c788e77ff51")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("1.0.0.0")]
diff --git a/Krypton v2.0/KryptonTestbed/KryptonTestbedContent/KryptonEffect.fx b/Krypton v2.0/KryptonTestbed/KryptonTestbedContent/KryptonEffect.fx
new file mode 100755
index 0000000..59abc92
--- /dev/null
+++ b/Krypton v2.0/KryptonTestbed/KryptonTestbedContent/KryptonEffect.fx
@@ -0,0 +1,478 @@
+// ------------------------------------------------------------------------------------------------ //
+// ----- Copyright 2011 Christopher Harris --------------------- http://krypton.codeplex.com/ ----- //
+// ----------------------------------------------------------------- mailto:xixonia@gmail.com ----- //
+// ------------------------------------------------------------------------------------------------ //
+
+// ------------------------------------------------------------------------------------------------ //
+// ----- Parameters ------------------------------------------------------------------------------- //
+
+float4x4 Matrix;
+
+texture Texture0;
+texture Texture1;
+float2 LightPosition;
+float LightIntensityFactor = 1;
+
+float ShadowStrech = 1000000;
+
+float2 TexelBias;
+
+float4 AmbientColor;
+
+float Bluriness = 0.5f;
+float BlurFactorU = 0;
+float BlurFactorV = 0;
+
+// ------------------------------------------------------------------------------------------------ //
+// ----- Samplers --------------------------------------------------------------------------------- //
+
+sampler2D tex0 = sampler_state
+{
+ Texture = ;
+ AddressU = Clamp;
+ AddressV = Clamp;
+};
+
+sampler2D tex1 = sampler_state
+{
+ Texture = ;
+ AddressU = Clamp;
+ AddressV = Clamp;
+};
+
+// ------------------------------------------------------------------------------------------------ //
+// ----- Structures ------------------------------------------------------------------------------- //
+
+struct ShadowHullVertex
+{
+ float4 Position : POSITION0;
+ float2 Normal : NORMAL0;
+ float4 Color : COLOR0;
+};
+
+struct VertexPositionColor
+{
+ float4 Position : POSITION0;
+ float4 Color : COLOR0;
+};
+
+struct VertexPositionNormalTexture
+{
+ float4 Position : POSITION0;
+ float4 Normal : NORMAL0;
+ float2 TexCoord : TEXCOORD0;
+};
+
+struct VertexPositionColorTexture
+{
+ float4 Position : POSITION0;
+ float4 Color : COLOR0;
+ float2 TexCoord : TEXCOORD0;
+};
+
+struct VertexPositionTexture
+{
+ float4 Position : POSITION0;
+ float2 TexCoord : TEXCOORD0;
+};
+
+// ------------------------------------------------------------------------------------------------ //
+// ----- Techniques ------------------------------------------------------------------------------- //
+
+// ------------------------------------------------------------------------------------------------
+// ----- Technique: TextureToTarget ---------------------------------------------------------------
+
+VertexPositionTexture VS_ScreenCopy(VertexPositionTexture input)
+{
+ VertexPositionTexture output;
+
+ output.Position = input.Position;
+ output.TexCoord = input.TexCoord;
+
+ return input;
+};
+
+float4 PS_ScreenCopy(VertexPositionTexture input) : COLOR0
+{
+ return tex2D(tex0, input.TexCoord + TexelBias);
+};
+
+technique TextureToTarget_Add
+{
+ pass Pass1
+ {
+ StencilEnable = False;
+
+ BlendOp = Add;
+ SrcBlend = One;
+ DestBlend = One;
+
+ AlphaBlendEnable = True;
+
+ CullMode = CCW;
+
+ VertexShader = compile vs_2_0 VS_ScreenCopy();
+ PixelShader = compile ps_2_0 PS_ScreenCopy();
+ }
+};
+
+technique TextureToTarget_Multiply
+{
+ pass Pass1
+ {
+ StencilEnable = False;
+
+ BlendOp = Add;
+ SrcBlend = Zero;
+ DestBlend = SrcColor;
+
+ AlphaBlendEnable = True;
+
+ CullMode = CCW;
+
+ VertexShader = compile vs_2_0 VS_ScreenCopy();
+ PixelShader = compile ps_2_0 PS_ScreenCopy();
+ }
+};
+
+float4 PS_ClearTarget() : COLOR0
+{
+ return float4(0, 0, 0, 1);
+}
+
+// ------------------------------------------------------------------------------------------------
+// ----- Technique: SimpleTexture -----------------------------------------------------------------
+
+VertexPositionColorTexture VS_SimpleTexture(VertexPositionColorTexture input)
+{
+ VertexPositionColorTexture output;
+
+ output.Position = mul(input.Position, Matrix);
+ output.Color = input.Color;
+ output.TexCoord = input.TexCoord;
+
+ return output;
+};
+
+float4 PS_SimpleTexture(VertexPositionColorTexture input) : COLOR0
+{
+ return tex2D(tex0, input.TexCoord) * input.Color;
+};
+
+float4 PS_LightTexture(VertexPositionColorTexture input) : COLOR0
+{
+ return pow(tex2D(tex0, input.TexCoord) * input.Color, LightIntensityFactor);
+};
+
+technique SimpleTexture
+{
+ pass Pass1
+ {
+ StencilEnable = False;
+
+ VertexShader = compile vs_2_0 VS_SimpleTexture();
+ PixelShader = compile ps_2_0 PS_SimpleTexture();
+ }
+};
+
+technique LightTexture
+{
+ pass Pass1
+ {
+ StencilEnable = False;
+
+ BlendOp = Add;
+ DestBlend = Zero;
+ SrcBlend = SrcAlpha;
+
+ AlphaBlendEnable = True;
+
+ VertexShader = compile vs_2_0 VS_SimpleTexture();
+ PixelShader = compile ps_2_0 PS_LightTexture();
+ }
+};
+
+// ------------------------------------------------------------------------------------------------
+// ----- Technique: PointLight_Shadow -------------------------------------------------------------
+
+VertexPositionColor VS_PointLight_Shadow(ShadowHullVertex input)
+{
+ float2 direction = normalize(LightPosition.xy - input.Position.xy);
+
+ if(dot(input.Normal.xy, direction) < 0)
+ {
+ // Stretch backfacing vertices
+ input.Position.xy -= direction * ShadowStrech;
+ }
+
+ VertexPositionColor output;
+
+ output.Position = mul(input.Position, Matrix);
+ output.Color = input.Color;
+
+ return output;
+};
+
+float4 PS_PointLight_Shadow(float4 input : COLOR0) : COLOR0
+{
+ return input;
+};
+
+VertexPositionColor VS_Shadow_HullIllumination(ShadowHullVertex input)
+{
+ VertexPositionColor output;
+
+ output.Position = mul(input.Position, Matrix);
+ output.Color = input.Color;
+
+ return output;
+};
+
+float4 PS_Shadow_HullIllumination() : COLOR0
+{
+ return float4(1, 1, 1, 1);
+};
+
+technique PointLight_Shadow
+{
+ pass Shadow
+ {
+ StencilEnable = False;
+
+ AlphaBlendEnable = True;
+
+ BlendOp = RevSubtract;
+ SrcBlend = One;
+ DestBlend = One;
+
+ VertexShader = compile vs_2_0 VS_PointLight_Shadow();
+ PixelShader = compile ps_2_0 PS_PointLight_Shadow();
+ }
+};
+
+// ------------------------------------------------------------------------------------------------
+// ----- Technique: PointLight_ShadowWithIllumination ---------------------------------------------
+
+technique PointLight_ShadowWithIllumination
+{
+ pass Shadow_Illumination
+ {
+ // This outlines where our hulls are currently, so we don't draw shadows there
+ StencilEnable = True;
+ StencilFunc = Never;
+ StencilFail = Incr;
+
+ AlphaBlendEnable = False;
+
+ VertexShader = compile vs_2_0 VS_Shadow_HullIllumination();
+ PixelShader = compile ps_2_0 PS_Shadow_HullIllumination();
+ }
+
+ pass Shadow
+ {
+ // Only draw where the Stencil hasn't touched
+ StencilEnable = True;
+ StencilFunc = Equal;
+ StencilRef = 0;
+ StencilFail = Incr;
+
+ AlphaBlendEnable = True;
+
+ BlendOp = RevSubtract;
+ SrcBlend = One;
+ DestBlend = One;
+
+ VertexShader = compile vs_2_0 VS_PointLight_Shadow();
+ PixelShader = compile ps_2_0 PS_PointLight_Shadow();
+ }
+
+};
+
+// ------------------------------------------------------------------------------------------------
+// ----- Technique: PointLight_ShadowWithOcclusion ------------------------------------------------
+
+technique PointLight_ShadowWithOcclusion
+{
+ pass Shadow_HullStencil
+ {
+ // This outlines where our hulls are currently, so we don't draw shadows there, unless the hull is occluded
+ StencilEnable = True;
+ StencilFunc = Never;
+ StencilFail = Incr;
+
+ VertexShader = compile vs_2_0 VS_Shadow_HullIllumination();
+ PixelShader = compile ps_2_0 PS_Shadow_HullIllumination();
+ }
+
+ pass Shadow
+ {
+ // This allows us to draw shadows on hulls behind other hulls
+ StencilEnable = True;
+ StencilFunc = NotEqual;
+ StencilRef = 1;
+ StencilPass = Keep;
+ StencilFail = Incr;
+
+ AlphaBlendEnable = True;
+
+ BlendOp = RevSubtract;
+ SrcBlend = One;
+ DestBlend = One;
+
+ VertexShader = compile vs_2_0 VS_PointLight_Shadow();
+ PixelShader = compile ps_2_0 PS_PointLight_Shadow();
+ }
+};
+
+// ------------------------------------------------------------------------------------------------
+// ----- Technique: DebugDraw ---------------------------------------------------------------------
+
+technique DebugDraw
+{
+ pass Solid
+ {
+ StencilEnable = False;
+ AlphaBlendEnable = False;
+
+ VertexShader = compile vs_2_0 VS_Shadow_HullIllumination();
+ PixelShader = compile ps_2_0 PS_Shadow_HullIllumination();
+ }
+};
+
+// ------------------------------------------------------------------------------------------------
+// ----- Technique: Blur --------------------------------------------------------------------------
+
+float4 PS_BlurH(in float2 texCoord : TEXCOORD0) : COLOR0
+{
+ float blurFactor = Bluriness * BlurFactorU / 4.0f;
+
+ return
+ tex2D(tex0, float2(texCoord.x - blurFactor * 4, texCoord.y) + TexelBias) * 0.05f +
+ tex2D(tex0, float2(texCoord.x - blurFactor * 3, texCoord.y) + TexelBias) * 0.09f +
+ tex2D(tex0, float2(texCoord.x - blurFactor * 2, texCoord.y) + TexelBias) * 0.12f +
+ tex2D(tex0, float2(texCoord.x - blurFactor, texCoord.y) + TexelBias) * 0.15f +
+ tex2D(tex0, float2(texCoord.x, texCoord.y) + TexelBias) * 0.18f +
+ tex2D(tex0, float2(texCoord.x + blurFactor, texCoord.y) + TexelBias) * 0.15f +
+ tex2D(tex0, float2(texCoord.x + blurFactor * 2, texCoord.y) + TexelBias) * 0.12f +
+ tex2D(tex0, float2(texCoord.x + blurFactor * 3, texCoord.y) + TexelBias) * 0.09f +
+ tex2D(tex0, float2(texCoord.x + blurFactor * 4, texCoord.y) + TexelBias) * 0.05f;
+}
+
+float4 PS_BlurV(in float2 texCoord : TEXCOORD0) : COLOR0
+{
+ float blurFactor = Bluriness * BlurFactorV / 4.0f;
+
+ return
+ tex2D(tex0, float2(texCoord.x, texCoord.y - blurFactor * 4) + TexelBias) * 0.05f +
+ tex2D(tex0, float2(texCoord.x, texCoord.y - blurFactor * 3) + TexelBias) * 0.09f +
+ tex2D(tex0, float2(texCoord.x, texCoord.y - blurFactor * 2) + TexelBias) * 0.12f +
+ tex2D(tex0, float2(texCoord.x, texCoord.y - blurFactor) + TexelBias) * 0.15f +
+ tex2D(tex0, float2(texCoord.x, texCoord.y) + TexelBias) * 0.18f +
+ tex2D(tex0, float2(texCoord.x, texCoord.y + blurFactor) + TexelBias) * 0.15f +
+ tex2D(tex0, float2(texCoord.x, texCoord.y + blurFactor * 2) + TexelBias) * 0.12f +
+ tex2D(tex0, float2(texCoord.x, texCoord.y + blurFactor * 3) + TexelBias) * 0.09f +
+ tex2D(tex0, float2(texCoord.x, texCoord.y + blurFactor * 4) + TexelBias) * 0.05f;
+}
+
+technique Blur
+{
+ pass HorizontalBlur
+ {
+ ScissorTestEnable = False;
+ StencilEnable = False;
+ AlphaBlendEnable = False;
+
+ CullMode = CCW;
+
+ VertexShader = compile vs_2_0 VS_ScreenCopy();
+ PixelShader = compile ps_2_0 PS_BlurH();
+ }
+
+ pass VerticalBlur
+ {
+ ScissorTestEnable = False;
+ StencilEnable = False;
+ AlphaBlendEnable = False;
+
+ CullMode = CCW;
+
+ VertexShader = compile vs_2_0 VS_ScreenCopy();
+ PixelShader = compile ps_2_0 PS_BlurV();
+ }
+}
+
+
+technique PointLight_Shadow_Fast
+{
+ pass ShadowStencil
+ {
+ StencilEnable = True;
+ StencilFunc = Always;
+ StencilPass = Incr;
+
+ ScissorTestEnable = True;
+
+ AlphaBlendEnable = True;
+ BlendOp = Add;
+ SrcBlend = DestAlpha;
+ DestBlend = Zero;
+
+ ColorWriteEnable = Alpha;
+
+ VertexShader = compile vs_2_0 VS_PointLight_Shadow();
+ PixelShader = compile ps_2_0 PS_PointLight_Shadow();
+ }
+
+ pass Light
+ {
+ StencilEnable = True;
+ StencilFunc = Equal;
+ StencilRef = 1;
+ StencilPass = Keep;
+
+ ScissorTestEnable = True;
+
+ AlphaBlendEnable = True;
+ BlendOp = Add;
+ SrcBlend = One;
+ DestBlend = One;
+
+ ColorWriteEnable = Red | Green | Blue;
+
+ VertexShader = compile vs_2_0 VS_SimpleTexture();
+ PixelShader = compile ps_2_0 PS_LightTexture();
+ }
+
+ pass LightAlpha
+ {
+ StencilEnable = True;
+ StencilFunc = NotEqual;
+ StencilRef = 1;
+ StencilPass = Keep;
+
+ ScissorTestEnable = True;
+
+ AlphaBlendEnable = True;
+ BlendOp = Add;
+ SrcBlend = DestAlpha;
+ DestBlend = One;
+
+ VertexShader = compile vs_2_0 VS_SimpleTexture();
+ PixelShader = compile ps_2_0 PS_LightTexture();
+ }
+
+ pass ClearAlpha
+ {
+ StencilEnable = False;
+
+ AlphaBlendEnable = False;
+
+ CullMode = CCW;
+
+ ColorWriteEnable = Alpha;
+
+ VertexShader = compile vs_2_0 VS_ScreenCopy();
+ PixelShader = compile ps_2_0 PS_ClearTarget();
+ }
+
+};
\ No newline at end of file
diff --git a/Krypton v2.0/KryptonTestbed/KryptonTestbedContent/KryptonTestbedContent.contentproj b/Krypton v2.0/KryptonTestbed/KryptonTestbedContent/KryptonTestbedContent.contentproj
new file mode 100755
index 0000000..b218d9d
--- /dev/null
+++ b/Krypton v2.0/KryptonTestbed/KryptonTestbedContent/KryptonTestbedContent.contentproj
@@ -0,0 +1,50 @@
+
+
+
+ {EA878F1A-4714-4377-8E6A-4947ACFF386A}
+ {96E2B04D-8817-42c6-938A-82C39BA4D311};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Debug
+ x86
+ Library
+ Properties
+ v4.0
+ v4.0
+ bin\$(Platform)\$(Configuration)
+ Content
+
+
+
+
+
+
+
+
+
+
+ KryptonTestbedContent
+
+
+
+ KryptonEffect
+ EffectImporter
+ EffectProcessor
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file