Compare commits

6 Commits

Author SHA1 Message Date
Simon Holmberg e732c9a653 Soldier flashlights! 2012-10-02 01:22:04 +02:00
Simon Holmberg 12f795f8bf Merge branch 'master' into krypton
Conflicts:
	DepthsBelow/DepthsBelow/Map.cs
2012-10-02 00:09:38 +02:00
Simon Holmberg d10a731721 Some new tilesets 2012-09-30 11:18:51 +02:00
Simon Holmberg 93466568f4 Updated Krypton 2012-09-30 11:17:59 +02:00
Simon Holmberg 7bcbe94e5f Yay, dynamic shadows! 2012-09-30 00:05:35 +02:00
Simon Holmberg a056127f7c Krypton lighting engine
http://krypton.codeplex.com/
2012-09-29 22:04:29 +02:00
53 changed files with 6769 additions and 38 deletions
+14 -1
View File
@@ -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\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
+5 -2
View File
@@ -42,18 +42,21 @@ namespace DepthsBelow
public void Update(GameTime gameTime)
{
if (!core.IsActive)
return;
float elapsed = gameTime.ElapsedGameTime.Milliseconds / 1000.0f;
MouseState ms = Mouse.GetState();
if (ms.X < 20)
Position.X += Speed * elapsed;
if (ms.X > core.GraphicsDevice.Viewport.Width - 20)
if (ms.X > Core.GraphicsDevice.Viewport.Width - 20)
Position.X -= Speed * elapsed;
if (ms.Y < 20)
Position.Y += Speed * elapsed;
if (ms.Y > core.GraphicsDevice.Viewport.Height - 20)
if (ms.Y > Core.GraphicsDevice.Viewport.Height - 20)
Position.Y -= Speed * elapsed;
int scrollChange = ms.ScrollWheelValue - lastMouseState.ScrollWheelValue;
+86
View File
@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
namespace DepthsBelow.Component
{
public class Flashlight : Component
{
public float Range
{
get { return KryptonLight.Range; }
set { KryptonLight.Range = value; }
}
public float Fov
{
get { return KryptonLight.Fov; }
set { KryptonLight.Fov = value; }
}
public float Intensity
{
get { return KryptonLight.Intensity; }
set { KryptonLight.Intensity = value; }
}
public float Angle
{
get { return KryptonLight.Angle; }
set { KryptonLight.Angle = value; }
}
public Vector2 Position
{
get { return KryptonLight.Position; }
set { KryptonLight.Position = value; }
}
public Color Color
{
get { return KryptonLight.Color; }
set { KryptonLight.Color = value; }
}
public bool IsOn
{
get { return KryptonLight.IsOn; }
set { KryptonLight.IsOn = value; }
}
public Krypton.Lights.ShadowType ShadowType
{
get { return KryptonLight.ShadowType; }
set { KryptonLight.ShadowType = value; }
}
public Krypton.Lights.Light2D KryptonLight;
public Flashlight(Entity parent)
: base(parent)
{
KryptonLight = new Krypton.Lights.Light2D()
{
Texture = Krypton.LightTextureBuilder.CreatePointLight(Core.GraphicsDevice, 512),
Range = (float)(100),
Position = parent.Transform.World + Parent.Transform.World.Origin,
Angle = parent.Transform.World.Rotation,
Color = Color.White,
Intensity = 1f,
Fov = MathHelper.TwoPi,
IsOn = true,
ShadowType = Krypton.Lights.ShadowType.Illuminated
};
}
public static explicit operator Krypton.Lights.Light2D(Flashlight flashlight)
{
return flashlight.KryptonLight;
}
public override void Update(GameTime gameTime)
{
Position = Parent.Transform.World + Parent.Transform.World.Origin;
Angle = Parent.Transform.World.Rotation;
}
}
}
+84 -17
View File
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Krypton.Lights;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
@@ -16,9 +17,12 @@ namespace DepthsBelow
/// </summary>
public class Core : Microsoft.Xna.Framework.Game
{
public static GraphicsDevice GraphicsDevice;
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
public Krypton.KryptonEngine KryptonEngine;
public Camera Camera;
public static MouseInput MouseInput;
@@ -39,6 +43,8 @@ namespace DepthsBelow
graphics.ApplyChanges();
this.IsMouseVisible = true;
}
/// <summary>
@@ -49,7 +55,16 @@ namespace DepthsBelow
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
GraphicsDevice = graphics.GraphicsDevice;
KryptonEngine = new Krypton.KryptonEngine(this, "KryptonEffect");
// Initialize lighting engine
this.KryptonEngine.Initialize();
this.KryptonEngine.SpriteBatchCompatablityEnabled = true;
this.KryptonEngine.CullMode = CullMode.CullClockwiseFace;
this.KryptonEngine.AmbientColor = new Color(35, 35, 35);
Camera = new Camera(this);
Squad = new List<Soldier>();
@@ -63,11 +78,41 @@ namespace DepthsBelow
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
spriteBatch = new SpriteBatch(Core.GraphicsDevice);
Map = Content.Load<Map>("maps/Cave.Level1");
// Load map objects
Map.ParseObjects(this);
Map.Initialize(this, KryptonEngine);
// DEBUG: Test lights
/*var light = new Krypton.Lights.Light2D()
{
Texture = Krypton.LightTextureBuilder.CreatePointLight(Core.GraphicsDevice, 512),
Range = (float)(500),
Color = Color.White,
Intensity = 1f,
Angle = MathHelper.TwoPi,
X = 17 * Grid.TileSize,
Y = 7 * Grid.TileSize,
Fov = MathHelper.TwoPi / 15,
IsOn = true,
ShadowType = ShadowType.Illuminated
};
this.KryptonEngine.Lights.Add(light);*/
var light = new Krypton.Lights.Light2D()
{
Texture = Krypton.LightTextureBuilder.CreatePointLight(Core.GraphicsDevice, 512),
Range = (float)(100),
Color = Color.White,
Intensity = 1f,
Angle = MathHelper.TwoPi,
X = 17 * Grid.TileSize,
Y = 7 * Grid.TileSize,
Fov = MathHelper.TwoPi,
IsOn = true,
ShadowType = ShadowType.Illuminated
};
this.KryptonEngine.Lights.Add(light);
// TODO: use this.Content to load your game content here
Soldier.LoadContent(this);
@@ -103,6 +148,9 @@ namespace DepthsBelow
foreach (var soldier in Squad)
soldier.Update(gameTime);
//foreach (Krypton.Lights.Light2D light in KryptonEngine.Lights)
// light.Position = Camera.ScreenToWorld(new Vector2(Mouse.GetState().X, Mouse.GetState().Y));
base.Update(gameTime);
}
@@ -112,25 +160,44 @@ namespace DepthsBelow
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
// Assign the matrix and pre-render the lightmap.
this.KryptonEngine.Matrix = Camera.Transform;
this.KryptonEngine.Bluriness = 1;
this.KryptonEngine.LightMapPrepare();
GraphicsDevice.Clear(Color.Black);
// Start drawing using the Camera transform
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null,
Camera.Transform);
/*
* Draw game world
*/
//GraphicsDevice.BlendState = BlendState.AlphaBlend;
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, null, null, null, Camera.Transform);
// Draw the level
Map.Draw(spriteBatch);
// Draw the level
Map.Draw(spriteBatch);
// Draw units
foreach (var soldier in Squad)
{
var sr = soldier.GetComponent<Component.SpriteRenderer>();
if (sr != null)
sr.Draw(spriteBatch);
}
// Draw units
foreach (var soldier in Squad)
{
var sr = soldier.GetComponent<Component.SpriteRenderer>();
if (sr != null)
sr.Draw(spriteBatch);
}
// Draw mouse input visuals
MouseInput.Draw(spriteBatch);
spriteBatch.End();
/*
* Draw Krypton lighting
*/
this.KryptonEngine.Draw(gameTime);
/*
* Draw HUD elements
*/
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, Camera.Transform);
// Draw mouse input visuals
MouseInput.Draw(spriteBatch);
spriteBatch.End();
@@ -122,6 +122,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Camera.cs" />
<Compile Include="Component\Flashlight.cs" />
<Compile Include="Component\PathFinder.cs" />
<Compile Include="Component\Transform.cs" />
<Compile Include="Grid.cs" />
@@ -147,6 +148,10 @@
<Project>{CD3F949D-54AA-4D38-99DB-92905A375D84}</Project>
<Name>AStar</Name>
</ProjectReference>
<ProjectReference Include="..\..\Krypton\Krypton\Krypton.csproj">
<Project>{B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}</Project>
<Name>Krypton</Name>
</ProjectReference>
<ProjectReference Include="..\DepthsBelowContent\DepthsBelowContent.contentproj">
<Name>DepthsBelowContent %28Content%29</Name>
<XnaReferenceType>Content</XnaReferenceType>
+56 -14
View File
@@ -59,29 +59,71 @@ namespace DepthsBelow
}
public void ParseObjects(Core core)
public void Initialize(Core core, Krypton.KryptonEngine kryptonEngine)
{
foreach (var layer in Layers)
{
var objectLayer = layer as MapObjectLayer;
if (objectLayer == null)
continue;
foreach (var mapObject in objectLayer.Objects)
if (objectLayer != null)
{
if (mapObject.Type == "SquadStart")
// Parse lighting engine hulls
/*if (objectLayer.Name == "Opaque")
{
var soldier = new Soldier(core, ref core.Squad);
// HACK: For some reason, the tile object coordinates are offset by one tile on the Y-axis in the Tiled map file (https://github.com/bjorn/tiled/issues/91)
var mapObjectPos = new Vector2(mapObject.Bounds.X, mapObject.Bounds.Y - Grid.TileSize);
var mapObjectGridPos = Grid.WorldToGrid(mapObjectPos);
soldier.X = mapObjectGridPos.X;
soldier.Y = mapObjectGridPos.Y;
foreach (var hullObject in objectLayer.Objects)
{
Console.WriteLine("Width: " + hullObject.Bounds.Width);
Console.WriteLine("Height: " + hullObject.Bounds.Height);
Console.WriteLine(hullObject.Bounds.X + ", " + hullObject.Bounds.Y);
Krypton.ShadowHull hull = Krypton.ShadowHull.CreateRectangle(new Vector2(hullObject.Bounds.Width, hullObject.Bounds.Height));
hull.Position.X = hullObject.Bounds.X + hullObject.Bounds.Width / 2;
hull.Position.Y = hullObject.Bounds.Y + hullObject.Bounds.Height / 2;
kryptonEngine.Hulls.Add(hull);
}
}*/
core.Squad.Add(soldier);
// Parse general objects
foreach (var mapObject in objectLayer.Objects)
{
if (mapObject.Type == "SquadStart")
{
// HACK: Move the entity creation to an entity factory
var soldier = new Soldier(core, ref core.Squad);
core.KryptonEngine.Lights.Add((Krypton.Lights.Light2D)soldier.GetComponent<Component.Flashlight>());
// HACK: For some reason, the tile object coordinates are offset by one tile on the Y-axis in the Tiled map file (https://github.com/bjorn/tiled/issues/91)
var mapObjectPos = new Vector2(mapObject.Bounds.X, mapObject.Bounds.Y - Grid.TileSize);
var mapObjectGridPos = Grid.WorldToGrid(mapObjectPos);
soldier.X = mapObjectGridPos.X;
soldier.Y = mapObjectGridPos.Y;
core.Squad.Add(soldier);
}
}
}
var tileLayer = layer as MapTileLayer;
if (tileLayer != null)
{
// Prepare collision hulls for lighting engine
if (tileLayer.Name == "Collision")
{
for (int y = 0; y < tileLayer.Height; y++)
{
for (int x = 0; x < tileLayer.Width; x++)
{
MapTile mapTile = tileLayer.Tiles[y * layer.Width + x];
if (mapTile != null && mapTile.LocalId != 0)
{
var hull = Krypton.ShadowHull.CreateRectangle(new Vector2(TileWidth, TileHeight));
hull.Position.X = x * TileWidth + TileWidth/2;
hull.Position.Y = y * TileHeight + TileWidth / 2;
kryptonEngine.Hulls.Add(hull);
}
}
}
}
}
}
}
+7 -3
View File
@@ -36,15 +36,19 @@ namespace DepthsBelow
public void LoadContent()
{
selectionTexture = new Texture2D(core.GraphicsDevice, 1, 1);
selectionTexture = new Texture2D(Core.GraphicsDevice, 1, 1);
selectionTexture.SetData(new Color[] { Color.White });
gridTexture = new Texture2D(core.GraphicsDevice, 1, 1);
gridTexture = new Texture2D(Core.GraphicsDevice, 1, 1);
gridTexture.SetData(new Color[] { Color.White });
}
public void Update(GameTime gameTime)
{
// Only capture input if the game window is in focus
if (!core.IsActive)
return;
MouseState ms = Mouse.GetState();
Vector2 mouseWorldPos = core.Camera.ScreenToWorld(new Vector2(ms.X, ms.Y));
KeyboardState ks = Keyboard.GetState();
@@ -149,7 +153,7 @@ namespace DepthsBelow
if (checkingDirection == true)
{
Texture2D blank = new Texture2D(core.GraphicsDevice, 1, 1, false, SurfaceFormat.Color);
Texture2D blank = new Texture2D(Core.GraphicsDevice, 1, 1, false, SurfaceFormat.Color);
blank.SetData(new[] { Color.White });
DrawLine(spriteBatch, blank, 2, Color.White, directionStart, directionNow);
}
+6
View File
@@ -36,6 +36,12 @@ namespace DepthsBelow
var pfc = new PathFinder(this);
AddComponent(pfc);
AddComponent(new Flashlight(this)
{
Range = 200,
Fov = MathHelper.PiOver4
});
}
public bool Selected
@@ -51,6 +51,7 @@
<Name>test</Name>
<Importer>TmxImporter</Importer>
<Processor>MapProcessor</Processor>
<SubType>Designer</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
@@ -99,6 +100,13 @@
<Processor>TextureProcessor</Processor>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="KryptonEffect.fx">
<Name>KryptonEffect</Name>
<Importer>EffectImporter</Importer>
<Processor>EffectProcessor</Processor>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\$(XnaFrameworkVersion)\Microsoft.Xna.GameStudio.ContentPipeline.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
+438
View File
@@ -0,0 +1,438 @@
// ------------------------------------------------------------------------------------------------ //
// ----- 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 = <Texture0>;
AddressU = Clamp;
AddressV = Clamp;
};
sampler2D tex1 = sampler_state
{
Texture = <Texture1>;
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 VertexPositionColorTexture
{
float4 Position : POSITION0;
float4 Color : COLOR0;
float2 TexCoord : TEXCOORD0;
};
struct VertexPositionTexture
{
float4 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
};
struct Color2
{
float4 Color0 : COLOR0;
float4 Color1 : COLOR1;
};
// ------------------------------------------------------------------------------------------------ //
// ----- Vertex Shaders --------------------------------------------------------------------------- //
VertexPositionTexture VS_TextureNoTransform(VertexPositionTexture input)
{
return input;
};
VertexPositionColorTexture VS_ColorTexture(VertexPositionColorTexture input)
{
input.Position = mul(input.Position, Matrix);
return input;
};
VertexPositionColor VS_Hull(ShadowHullVertex input)
{
VertexPositionColor output;
output.Position = mul(input.Position, Matrix);
output.Color = input.Color;
return output;
};
VertexPositionColor VS_Hull_RadialStretch(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;
};
// ------------------------------------------------------------------------------------------------ //
// ----- Pixel Shaders ---------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------ //
// ----- Techniques ------------------------------------------------------------------------------- //
float4 PS_Texture(in float2 texCoord : TEXCOORD0) : COLOR0
{
return tex2D(tex0, texCoord + TexelBias);
};
float4 PS_ColorTexture(in float4 color : COLOR0, in float2 texCoord : TEXCOORD0) : COLOR0
{
return tex2D(tex0, texCoord) * color;
};
float4 PS_LightTexture(VertexPositionColorTexture input) : COLOR0
{
return pow(abs(tex2D(tex0, input.TexCoord)) * input.Color, LightIntensityFactor);
};
float4 PS_Color(in float4 color : COLOR0) : COLOR0
{
return color;
};
float4 PS_White() : COLOR0
{
return float4(1, 1, 1, 1);
};
float4 PS_Black() : COLOR0
{
return float4(0, 0, 0, 1);
};
float4 PS_Debug() : COLOR0
{
return float4(1, 0, 0, 1);
};
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: TextureToTarget ---------------------------------------------------------------
technique TextureToTarget_Add
{
pass Pass1
{
StencilEnable = False;
BlendOp = Add;
SrcBlend = One;
DestBlend = One;
AlphaBlendEnable = True;
CullMode = CCW;
VertexShader = compile vs_2_0 VS_TextureNoTransform();
PixelShader = compile ps_2_0 PS_Texture();
}
};
technique TextureToTarget_Multiply
{
pass Pass1
{
StencilEnable = False;
BlendOp = Add;
SrcBlend = Zero;
DestBlend = SrcColor;
AlphaBlendEnable = True;
CullMode = CCW;
VertexShader = compile vs_2_0 VS_TextureNoTransform();
PixelShader = compile ps_2_0 PS_Texture();
}
};
technique LightTexture
{
pass Pass1
{
StencilEnable = False;
BlendOp = Add;
DestBlend = Zero;
SrcBlend = SrcAlpha;
AlphaBlendEnable = True;
VertexShader = compile vs_2_0 VS_ColorTexture();
PixelShader = compile ps_2_0 PS_LightTexture();
}
};
// ------------------------------------------------------------------------------------------------
// ----- Technique: PointLight_Shadow -------------------------------------------------------------
technique PointLight_Shadow_Solid
{
pass Shadow
{
StencilEnable = False;
ScissorTestEnable = True;
AlphaBlendEnable = True;
BlendOp = Add;
SrcBlend = DestColor;
DestBlend = Zero;
ColorWriteEnable = Alpha;
VertexShader = compile vs_2_0 VS_Hull_RadialStretch();
PixelShader = compile ps_2_0 PS_Color();
}
};
technique PointLight_Shadow_Illuminated
{
pass Shadow
{
StencilEnable = False;
ScissorTestEnable = True;
AlphaBlendEnable = True;
BlendOp = Add;
SrcBlend = DestAlpha;
DestBlend = Zero;
ColorWriteEnable = Alpha;
VertexShader = compile vs_2_0 VS_Hull_RadialStretch();
PixelShader = compile ps_2_0 PS_Color();
}
pass Hull
{
StencilEnable = False;
ScissorTestEnable = True;
AlphaBlendEnable = True;
BlendOp = Add;
SrcBlend = One;
DestBlend = Zero;
ColorWriteEnable = Alpha;
VertexShader = compile vs_2_0 VS_Hull();
PixelShader = compile ps_2_0 PS_White();
}
};
technique PointLight_Shadow_Occluded
{
pass Shadow
{
StencilEnable = True;
StencilFunc = Always;
StencilPass = IncrSat;
StencilFail = Keep;
ScissorTestEnable = True;
AlphaBlendEnable = True;
BlendOp = Add;
SrcBlend = DestAlpha;
DestBlend = Zero;
ColorWriteEnable = Alpha;
VertexShader = compile vs_2_0 VS_Hull_RadialStretch();
PixelShader = compile ps_2_0 PS_Color();
}
pass Hull
{
StencilEnable = True;
StencilFunc = Equal;
StencilRef = 1;
StencilPass = Keep;
ScissorTestEnable = True;
AlphaBlendEnable = True;
BlendOp = Add;
SrcBlend = One;
DestBlend = Zero;
ColorWriteEnable = Alpha;
VertexShader = compile vs_2_0 VS_Hull();
PixelShader = compile ps_2_0 PS_White();
}
};
technique PointLight_Light
{
pass Light
{
StencilEnable = False;
ScissorTestEnable = False;
AlphaBlendEnable = True;
BlendOp = Add;
SrcBlend = DestAlpha;
DestBlend = One;
ColorWriteEnable = Red | Green | Blue;
VertexShader = compile vs_2_0 VS_ColorTexture();
PixelShader = compile ps_2_0 PS_LightTexture();
}
};
technique ClearTarget_Alpha
{
pass Pass1
{
StencilEnable = False;
AlphaBlendEnable = True;
BlendOp = Add;
SrcBlend = One;
DestBlend = One;
ScissorTestEnable = True;
ColorWriteEnable = Red | Green | Blue | Alpha;
VertexShader = compile vs_2_0 VS_TextureNoTransform();
PixelShader = compile ps_2_0 PS_Black();
}
};
// ------------------------------------------------------------------------------------------------
// ----- Technique: Blur --------------------------------------------------------------------------
technique Blur
{
pass HorizontalBlur
{
ScissorTestEnable = False;
StencilEnable = False;
AlphaBlendEnable = False;
CullMode = CCW;
VertexShader = compile vs_2_0 VS_TextureNoTransform();
PixelShader = compile ps_2_0 PS_BlurH();
}
pass VerticalBlur
{
ScissorTestEnable = False;
StencilEnable = False;
AlphaBlendEnable = False;
CullMode = CCW;
VertexShader = compile vs_2_0 VS_TextureNoTransform();
PixelShader = compile ps_2_0 PS_BlurV();
}
}
// ------------------------------------------------------------------------------------------------
// ----- Technique: DebugDraw ---------------------------------------------------------------------
technique DebugDraw
{
pass Solid
{
StencilEnable = False;
AlphaBlendEnable = False;
VertexShader = compile vs_2_0 VS_Hull();
PixelShader = compile ps_2_0 PS_Debug();
}
};
+38
View File
@@ -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
+278
View File
@@ -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
{
/// <summary>
/// Much like Rectangle, but stored as two Vector2s
/// </summary>
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;
}
}
}
+98
View File
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}</ProjectGuid>
<ProjectTypeGuids>{6D335F3A-9D43-41b4-9D22-F6F17C4BE596};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Krypton</RootNamespace>
<AssemblyName>Krypton</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<XnaFrameworkVersion>v4.0</XnaFrameworkVersion>
<XnaPlatform>Windows</XnaPlatform>
<XnaProfile>HiDef</XnaProfile>
<XnaCrossPlatformGroupID>f22a3b67-7b26-4bcf-9fa4-831713f618f0</XnaCrossPlatformGroupID>
<XnaOutputType>Library</XnaOutputType>
<SccProjectName>
</SccProjectName>
<SccLocalPath>
</SccLocalPath>
<SccAuxPath>
</SccAuxPath>
<SccProvider>
</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\x86\Debug</OutputPath>
<DefineConstants>DEBUG;TRACE;WINDOWS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoStdLib>true</NoStdLib>
<UseVSHostingProcess>false</UseVSHostingProcess>
<PlatformTarget>x86</PlatformTarget>
<XnaCompressContent>false</XnaCompressContent>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\x86\Release</OutputPath>
<DefineConstants>TRACE;WINDOWS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoStdLib>true</NoStdLib>
<UseVSHostingProcess>false</UseVSHostingProcess>
<PlatformTarget>x86</PlatformTarget>
<XnaCompressContent>true</XnaCompressContent>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="mscorlib">
<Private>False</Private>
</Reference>
<Reference Include="System">
<Private>False</Private>
</Reference>
<Reference Include="System.Xml">
<Private>False</Private>
</Reference>
<Reference Include="System.Core">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
<Private>False</Private>
</Reference>
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Common\BoundingRect.cs" />
<Compile Include="KryptonEngine.cs" />
<Compile Include="Lights\ILight2D.cs" />
<Compile Include="LightTextureBuilder.cs" />
<Compile Include="Lights\Light2D.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="KryptonRenderHelper.cs" />
<Compile Include="ShadowHull.cs" />
<Compile Include="ShadowHullPoint.cs" />
<Compile Include="ShadowHullVertex.cs" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\Microsoft.Xna.GameStudio.targets" />
<!--
To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
+423
View File
@@ -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,
}
/// <summary>
/// A GPU-based 2D lighting engine
/// </summary>
public class KryptonEngine : DrawableGameComponent
{
// The Krypton Effect
private string mEffectAssetName;
private Effect mEffect;
private CullMode mCullMode = CullMode.CullCounterClockwiseFace;
// The goods
private List<ShadowHull> mHulls = new List<ShadowHull>();
private List<ILight2D> mLights = new List<ILight2D>();
// 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;
/// <summary>
/// Krypton's render helper. It helps render. It also needs to be re-written.
/// </summary>
public KryptonRenderHelper RenderHelper { get; private set; }
/// <summary>
/// Gets or sets a value indicating how Krypton should cull geometry. The default value is CullMode.CounterClockwise
/// </summary>
public CullMode CullMode
{
get { return this.mCullMode; }
set { this.mCullMode = value; }
}
/// <summary>
/// The collection of lights krypton uses to render shadows
/// </summary>
public List<ILight2D> Lights { get { return this.mLights; } }
/// <summary>
/// The collection of hulls krypton uses to render shadows
/// </summary>
public List<ShadowHull> Hulls { get { return this.mHulls; } }
/// <summary>
/// Gets or sets the matrix used to draw the light map. This should match your scene's matrix.
/// </summary>
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;
}
}
}
/// <summary>
/// Gets or sets a value indicating weither or not to use SpriteBatch's matrix when drawing lightmaps
/// </summary>
public bool SpriteBatchCompatablityEnabled
{
get { return this.mSpriteBatchCompatabilityEnabled; }
set { this.mSpriteBatchCompatabilityEnabled = value; }
}
/// <summary>
/// Ambient color of the light map. Lights + AmbientColor = Final
/// </summary>
public Color AmbientColor
{
get { return this.mAmbientColor; }
set { this.mAmbientColor = value; }
}
/// <summary>
/// Gets or sets the value used to determine light map size
/// </summary>
public LightMapSize LightMapSize
{
get { return this.mLightMapSize; }
set
{
if (this.mLightMapSize != value)
{
this.mLightMapSize = value;
this.DisposeRenderTargets();
this.CreateRenderTargets();
}
}
}
/// <summary>
/// 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
/// </summary>
public float Bluriness
{
get { return this.mBluriness; }
set { this.mBluriness = Math.Max(0, value); }
}
/// <summary>
/// Constructs a new instance of krypton
/// </summary>
/// <param name="game">Your game object</param>
/// <param name="effectAssetName">The asset name of Krypton's effect file, which must be included in your content project</param>
public KryptonEngine(Game game, string effectAssetName)
: base(game)
{
this.mEffectAssetName = effectAssetName;
}
/// <summary>
/// Initializes Krpyton, and hooks itself to the graphics device
/// </summary>
public override void Initialize()
{
base.Initialize();
this.GraphicsDevice.DeviceReset += new EventHandler<EventArgs>(GraphicsDevice_DeviceReset);
}
/// <summary>
/// Resets kryptons graphics device resources
/// </summary>
private void GraphicsDevice_DeviceReset(object sender, EventArgs e)
{
this.DisposeRenderTargets();
this.CreateRenderTargets();
}
/// <summary>
/// Load's the graphics related content required to draw light maps
/// </summary>
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<Effect>(this.mEffectAssetName);
this.RenderHelper = new KryptonRenderHelper(this.GraphicsDevice, this.mEffect);
this.CreateRenderTargets();
}
/// <summary>
/// Unload's the graphics content required to draw light maps
/// </summary>
protected override void UnloadContent()
{
this.DisposeRenderTargets();
}
/// <summary>
/// Creates render targets
/// </summary>
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);
}
/// <summary>
/// Disposes of render targets
/// </summary>
private void DisposeRenderTargets()
{
KryptonEngine.TryDispose(this.mMap);
KryptonEngine.TryDispose(this.mMapBlur);
}
/// <summary>
/// Attempts to dispose of disposable objects, and assigns them a null value afterward
/// </summary>
/// <param name="obj"></param>
private static void TryDispose(IDisposable obj)
{
if (obj != null)
{
obj.Dispose();
obj = null;
}
}
/// <summary>
/// Draws the light map to the current render target
/// </summary>
/// <param name="gameTime">N/A - Required</param>
public override void Draw(GameTime gameTime)
{
this.LightMapPresent();
}
/// <summary>
/// Prepares the light map to be drawn (pre-render)
/// </summary>
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);
}
/// <summary>
/// Returns the final, modified matrix used to render the lightmap.
/// </summary>
/// <returns></returns>
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;
}
}
/// <summary>
/// Gets a pixel-space rectangle which contains the light passed in
/// </summary>
/// <param name="light">The light used to create the rectangle</param>
/// <param name="matrix">the WorldViewProjection matrix being used to render</param>
/// <param name="targetSize">The rendertarget's size</param>
/// <returns></returns>
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));
}
/// <summary>
/// Takes a screen-space vector and puts it in to pixel space
/// </summary>
/// <param name="v"></param>
/// <param name="matrix"></param>
/// <param name="targetSize"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Takes a screen-space size vector and converts it to a pixel-space size vector
/// </summary>
/// <param name="v"></param>
/// <param name="matrix"></param>
/// <param name="targetSize"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Retrieves a rasterize state by using the cull mode as a lookup
/// </summary>
/// <param name="cullMode">The cullmode used to lookup the rasterize state</param>
/// <returns></returns>
private static RasterizerState RasterizerStateGetFromCullMode(CullMode cullMode)
{
switch (cullMode)
{
case (CullMode.CullCounterClockwiseFace):
return RasterizerState.CullCounterClockwise;
case (CullMode.CullClockwiseFace):
return RasterizerState.CullClockwise;
default:
return RasterizerState.CullNone;
}
}
/// <summary>
/// Presents the light map to the current render target
/// </summary>
private void LightMapPresent()
{
RenderHelper.DrawTextureToTarget(this.mMap, this.mLightMapSize, BlendTechnique.Multiply);
}
}
}
+476
View File
@@ -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<ShadowHullVertex> mShadowHullVertices = new List<ShadowHullVertex>();
private List<Int32> mShadowHullIndicies = new List<Int32>();
public GraphicsDevice GraphicsDevice
{
get { return this.mGraphicsDevice; }
}
public Effect Effect
{
get { return this.mEffect; }
}
public List<ShadowHullVertex> ShadowHullVertices
{
get { return this.mShadowHullVertices; }
}
public List<Int32> 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<VertexPositionColorTexture>(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<VertexPositionColorTexture>(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<ShadowHullVertex>(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<VertexPositionTexture>(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<VertexPositionTexture>(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<VertexPositionTexture>(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);
}
}
}
+89
View File
@@ -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
{
/// <summary>
/// Create a Point Light based on a size.
/// </summary>
/// <param name="device">Your game's GraphicsDevice</param>
/// <param name="size">Maximum Size</param>
/// <returns>Light Texture</returns>
public static Texture2D CreatePointLight(GraphicsDevice device, int size)
{
return CreateConicLight(device, size, MathHelper.TwoPi, 0);
}
/// <summary>
/// Create a Conic Light based on the size, and field of view.
/// </summary>
/// <param name="device">Your game's GraphicsDevice</param>
/// <param name="size">Maximum Size</param>
/// <param name="FOV">Maximum Field of View</param>
/// <returns>Light Texture</returns>
public static Texture2D CreateConicLight(GraphicsDevice device, int size, float FOV)
{
return CreateConicLight(device, size, FOV, 0);
}
/// <summary>
/// Create a Conic Light based on the size, field of view, and near plane distance.
/// </summary>
/// <param name="device">Your game's GraphicsDevice</param>
/// <param name="size">Maximum size</param>
/// <param name="FOV">Maximum Field of View</param>
/// <param name="nearPlaneDistance">Prevents texture from being drawn at this plane distance, originating from the center of light</param>
/// <returns>Light Texture</returns>
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<Color>(Data1D);
return tex;
}
/// <summary>
/// Math helper to determine if integer is a power of two
/// </summary>
/// <param name="x">Integer value</param>
private static bool IsPowerOfTwo(int x)
{
return (x & (x - 1)) == 0;
}
}
}
+17
View File
@@ -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<ShadowHull> hulls);
}
}
+192
View File
@@ -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
/// <summary>
/// The light's position
/// </summary>
public Vector2 Position
{
get { return this.mPosition; }
set { this.mPosition = value; }
}
/// <summary>
/// The X coordinate of the light's position
/// </summary>
public float X
{
get { return this.mPosition.X; }
set { this.mPosition.X = value; }
}
/// <summary>
/// The Y coordinate of the light's position
/// </summary>
public float Y
{
get { return this.mPosition.Y; }
set { this.mPosition.Y = value; }
}
/// <summary>
/// The light's angle
/// </summary>
public float Angle
{
get { return this.mAngle; }
set { this.mAngle = value; }
}
/// <summary>
/// The texture used as the base light map, from which shadows will be subtracted
/// </summary>
public Texture2D Texture
{
get { return this.mTexture; }
set { this.mTexture = value; }
}
/// <summary>
/// The color used to tint the light's texture
/// </summary>
public Color Color
{
get { return this.mColor; }
set { this.mColor = value; }
}
/// <summary>
/// The light's maximum radius (or "half width", if you will)
/// </summary>
public float Range
{
get { return this.mRange; }
set { this.mRange = value; }
}
/// <summary>
/// Gets or sets the light's field of view. This value determines the angles at which the light will cease to draw
/// </summary>
public float Fov
{
get { return this.mFov; }
set
{
this.mFov = MathHelper.Clamp(value, 0, MathHelper.TwoPi);
}
}
/// <summary>
/// Gets or sets the light's intensity. Think pixel = (tex * color) ^ (1 / intensity)
/// </summary>
public float Intensity
{
get { return this.mIntensity; }
set { this.mIntensity = MathHelper.Clamp(value, 0.01f, 3f); }
}
#endregion Parameters
/// <summary>
/// Gets or sets a value indicating weither or not to draw the light
/// </summary>
public bool IsOn
{
get { return this.mIsOn; }
set { this.mIsOn = value; }
}
/// <summary>
/// Draws shadows from the light's position outward
/// </summary>
/// <param name="helper">A render helper for drawing shadows</param>
/// <param name="hulls">The shadow hulls used to draw shadows</param>
public void Draw(KryptonRenderHelper helper, List<ShadowHull> 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);
}
/// <summary>
/// Determines if a vector's length is less than a specified value
/// </summary>
/// <param name="offset">Offset</param>
/// <param name="dist">Distance</param>
/// <returns></returns>
private static bool IsInRange(Vector2 offset, float dist)
{
if (offset.X * offset.X + offset.Y * offset.Y < dist * dist)
return true;
return false;
}
/// <summary>
/// Gets the world-space bounds which contain the light
/// </summary>
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;
}
}
}
}
+34
View File
@@ -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")]
+241
View File
@@ -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
{
/// <summary>
/// A hull used for casting shadows from a light source
/// </summary>
public class ShadowHull
{
#region Orientation
/// <summary>
/// The position of the shadow hull
/// </summary>
public Vector2 Position;
/// <summary>
/// The angle of the shadow hull
/// </summary>
public float Angle;
#endregion
#region Shape
/// <summary>
/// The maximum radius in which all of the shadow hull's vertices are contained, originating from the hull's position
/// </summary>
public float MaxRadius;
/// <summary>
/// The vertices comprising the shadow hull
/// </summary>
public ShadowHullPoint[] Points;
/// <summary>
/// The number of vertices comprising the shadow hull
/// </summary>
public int NumPoints;
/// <summary>
/// The indicies used to render the shadow hull
/// </summary>
public Int32[] Indicies;
/// <summary>
/// The number of indicies used to render the shadow hull
/// </summary>
public int NumIndicies;
/// <summary>
/// A value indicating if the hull should cast a shadow
/// </summary>
public bool Visible = true;
/// <summary>
/// A value indicating how much to stretch the hull
/// </summary>
public Vector2 Scale = Vector2.One;
#endregion
private ShadowHull(){}
#region Factory Methods
/// <summary>
/// Creates a rectangular shadow hull
/// </summary>
/// <param name="size">The dimensions of the rectangle</param>
/// <returns>A rectangular shadow hull</returns>
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;
}
/// <summary>
/// Creates a circular shadow hull
/// </summary>
/// <param name="radius">radius of the circle</param>
/// <param name="sides">number of sides the circle will be comprised of</param>
/// <returns>A circular shadow hull</returns>
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;
}
/// <summary>
/// Creates a custom shadow hull based on a series of vertices
/// </summary>
/// <param name="points">The points which the shadow hull will be comprised of</param>
/// <returns>A custom shadow hulll</returns>
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
}
}
+36
View File
@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
namespace Krypton
{
/// <summary>
/// A two dimensional point with normal
/// </summary>
public struct ShadowHullPoint
{
/// <summary>
/// Creates a new Shadow Hull Point
/// </summary>
/// <param name="position">The position of the point</param>
/// <param name="normal">The normal of the side which the point helps represent</param>
public ShadowHullPoint(Vector2 position, Vector2 normal)
{
this.Position = position;
this.Normal = normal;
}
/// <summary>
/// The position of the point
/// </summary>
public Vector2 Position;
/// <summary>
/// The normal of the side of the shadow hull of which the point helps represent
/// </summary>
public Vector2 Normal;
}
}
+60
View File
@@ -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
{
/// <summary>
/// The position of the vertex
/// </summary>
public Vector2 Position;
/// <summary>
/// The normal of the vertex
/// </summary>
public Vector2 Normal;
/// <summary>
/// The color of vertex
/// </summary>
public Color Color;
private static readonly VertexDeclaration mVertexDeclaration;
/// <summary>
///
/// </summary>
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);
}
/// <summary>
///
/// </summary>
/// <param name="position"></param>
/// <param name="normal"></param>
/// <param name="opacity"></param>
public ShadowHullVertex(Vector2 position, Vector2 normal, Color color)
{
this.Position = position;
this.Normal = normal;
this.Color = color;
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

@@ -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
{
/// <summary>
/// This is the main type for your game
/// </summary>
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();
}
}
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

@@ -0,0 +1,153 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{E9787BEE-7290-4C74-B919-79DC70AABE87}</ProjectGuid>
<ProjectTypeGuids>{6D335F3A-9D43-41b4-9D22-F6F17C4BE596};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>KryptonTestbed</RootNamespace>
<AssemblyName>KryptonTestbed</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<XnaFrameworkVersion>v4.0</XnaFrameworkVersion>
<XnaPlatform>Windows</XnaPlatform>
<XnaProfile>HiDef</XnaProfile>
<XnaCrossPlatformGroupID>04e8736f-6d19-442f-95e4-08f9b783d054</XnaCrossPlatformGroupID>
<XnaOutputType>Game</XnaOutputType>
<ApplicationIcon>Game.ico</ApplicationIcon>
<Thumbnail>GameThumbnail.png</Thumbnail>
<SccProjectName>
</SccProjectName>
<SccLocalPath>
</SccLocalPath>
<SccAuxPath>
</SccAuxPath>
<SccProvider>
</SccProvider>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\x86\Debug</OutputPath>
<DefineConstants>DEBUG;TRACE;WINDOWS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoStdLib>true</NoStdLib>
<UseVSHostingProcess>false</UseVSHostingProcess>
<PlatformTarget>x86</PlatformTarget>
<XnaCompressContent>false</XnaCompressContent>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\x86\Release</OutputPath>
<DefineConstants>TRACE;WINDOWS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoStdLib>true</NoStdLib>
<UseVSHostingProcess>false</UseVSHostingProcess>
<PlatformTarget>x86</PlatformTarget>
<XnaCompressContent>true</XnaCompressContent>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Avatar, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
<Reference Include="Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.GamerServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
<Reference Include="Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Input.Touch, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
<Reference Include="Microsoft.Xna.Framework.Net, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
<Reference Include="Microsoft.Xna.Framework.Storage, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
<Reference Include="Microsoft.Xna.Framework.Video, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
<Reference Include="Microsoft.Xna.Framework.Xact, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="mscorlib">
<Private>False</Private>
</Reference>
<Reference Include="System">
<Private>False</Private>
</Reference>
<Reference Include="System.Xml">
<Private>False</Private>
</Reference>
<Reference Include="System.Core">
<Private>False</Private>
</Reference>
<Reference Include="System.Xml.Linq">
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Program.cs" />
<Compile Include="GameKryptonDemo.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Game.ico" />
<Content Include="GameThumbnail.png" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Krypton\Krypton.csproj">
<Project>{B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}</Project>
<Name>Krypton</Name>
</ProjectReference>
<ProjectReference Include="..\KryptonTestbedContent\KryptonTestbedContent.contentproj">
<Name>KryptonTestbedContent</Name>
<XnaReferenceType>Content</XnaReferenceType>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4 Client Profile %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Xna.Framework.4.0">
<Visible>False</Visible>
<ProductName>Microsoft XNA Framework Redistributable 4.0</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\Microsoft.Xna.GameStudio.targets" />
<!--
To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
+21
View File
@@ -0,0 +1,21 @@
using System;
namespace KryptonTestbed
{
#if WINDOWS || XBOX
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
using (KryptonDemoGame game = new KryptonDemoGame())
{
game.Run();
}
}
}
#endif
}
@@ -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")]
@@ -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 = <Texture0>;
AddressU = Clamp;
AddressV = Clamp;
};
sampler2D tex1 = sampler_state
{
Texture = <Texture1>;
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();
}
};
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<ProjectGuid>{EA878F1A-4714-4377-8E6A-4947ACFF386A}</ProjectGuid>
<ProjectTypeGuids>{96E2B04D-8817-42c6-938A-82C39BA4D311};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<XnaFrameworkVersion>v4.0</XnaFrameworkVersion>
<OutputPath>bin\$(Platform)\$(Configuration)</OutputPath>
<ContentRootDirectory>Content</ContentRootDirectory>
<SccProjectName>
</SccProjectName>
<SccLocalPath>
</SccLocalPath>
<SccAuxPath>
</SccAuxPath>
<SccProvider>
</SccProvider>
</PropertyGroup>
<PropertyGroup>
<RootNamespace>KryptonTestbedContent</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Include="KryptonEffect.fx">
<Name>KryptonEffect</Name>
<Importer>EffectImporter</Importer>
<Processor>EffectProcessor</Processor>
</Compile>
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline.AudioImporters, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline.EffectImporter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline.FBXImporter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline.TextureImporter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline.VideoImporters, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline.XImporter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\$(XnaFrameworkVersion)\Microsoft.Xna.GameStudio.ContentPipeline.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
+75
View File
@@ -0,0 +1,75 @@
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("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3A5C565D-761D-484C-B0BB-57BA2AC2A909}"
ProjectSection(SolutionItems) = preProject
Krypton.vsmdi = Krypton.vsmdi
Local.testsettings = Local.testsettings
TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings
EndProjectSection
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(TeamFoundationVersionControl) = preSolution
SccNumberOfProjects = 4
SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C}
SccTeamFoundationServer = https://tfs.codeplex.com/tfs/tfs24
SccLocalPath0 = .
SccProjectUniqueName1 = Krypton\\Krypton.csproj
SccProjectName1 = Krypton
SccLocalPath1 = Krypton
SccProjectUniqueName2 = KryptonTestbed\\KryptonTestbed\\KryptonTestbed.csproj
SccProjectName2 = KryptonTestbed/KryptonTestbed
SccLocalPath2 = KryptonTestbed\\KryptonTestbed
SccProjectUniqueName3 = KryptonTestbed\\KryptonTestbedContent\\KryptonTestbedContent.contentproj
SccProjectName3 = KryptonTestbed/KryptonTestbedContent
SccLocalPath3 = KryptonTestbed\\KryptonTestbedContent
EndGlobalSection
GlobalSection(TestCaseManagementSettings) = postSolution
CategoryFile = Krypton.vsmdi
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|Mixed Platforms = Release|Mixed Platforms
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|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
{E9787BEE-7290-4C74-B919-79DC70AABE87}.Debug|Any CPU.ActiveCfg = Debug|x86
{E9787BEE-7290-4C74-B919-79DC70AABE87}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{E9787BEE-7290-4C74-B919-79DC70AABE87}.Debug|Mixed Platforms.Build.0 = 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|Mixed Platforms.ActiveCfg = Release|x86
{E9787BEE-7290-4C74-B919-79DC70AABE87}.Release|Mixed Platforms.Build.0 = 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|Mixed Platforms.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|Mixed Platforms.ActiveCfg = Debug|Any CPU
{EA878F1A-4714-4377-8E6A-4947ACFF386A}.Release|x86.ActiveCfg = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<TestLists xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<TestList name="Lists of Tests" id="8c43106b-9dc1-4907-a29f-aa66a61bf5b6">
<RunConfiguration id="aa1589e6-aa53-4011-abe6-96c924b63399" name="Local" storage="local.testsettings" type="Microsoft.VisualStudio.TestTools.Common.TestRunConfiguration, Microsoft.VisualStudio.QualityTools.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</TestList>
</TestLists>
+278
View File
@@ -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
{
/// <summary>
/// Much like Rectangle, but stored as two Vector2s
/// </summary>
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;
}
}
}
+98
View File
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}</ProjectGuid>
<ProjectTypeGuids>{6D335F3A-9D43-41b4-9D22-F6F17C4BE596};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Krypton</RootNamespace>
<AssemblyName>Krypton</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<XnaFrameworkVersion>v4.0</XnaFrameworkVersion>
<XnaPlatform>Windows</XnaPlatform>
<XnaProfile>HiDef</XnaProfile>
<XnaCrossPlatformGroupID>f22a3b67-7b26-4bcf-9fa4-831713f618f0</XnaCrossPlatformGroupID>
<XnaOutputType>Library</XnaOutputType>
<SccProjectName>
</SccProjectName>
<SccLocalPath>
</SccLocalPath>
<SccAuxPath>
</SccAuxPath>
<SccProvider>
</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\x86\Debug</OutputPath>
<DefineConstants>DEBUG;TRACE;WINDOWS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoStdLib>true</NoStdLib>
<UseVSHostingProcess>false</UseVSHostingProcess>
<PlatformTarget>x86</PlatformTarget>
<XnaCompressContent>false</XnaCompressContent>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\x86\Release</OutputPath>
<DefineConstants>TRACE;WINDOWS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoStdLib>true</NoStdLib>
<UseVSHostingProcess>false</UseVSHostingProcess>
<PlatformTarget>x86</PlatformTarget>
<XnaCompressContent>true</XnaCompressContent>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="mscorlib">
<Private>False</Private>
</Reference>
<Reference Include="System">
<Private>False</Private>
</Reference>
<Reference Include="System.Xml">
<Private>False</Private>
</Reference>
<Reference Include="System.Core">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
<Private>False</Private>
</Reference>
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Common\BoundingRect.cs" />
<Compile Include="KryptonEngine.cs" />
<Compile Include="Lights\ILight2D.cs" />
<Compile Include="LightTextureBuilder.cs" />
<Compile Include="Lights\Light2D.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="KryptonRenderHelper.cs" />
<Compile Include="ShadowHull.cs" />
<Compile Include="ShadowHullPoint.cs" />
<Compile Include="ShadowHullVertex.cs" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\Microsoft.Xna.GameStudio.targets" />
<!--
To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
+423
View File
@@ -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,
}
/// <summary>
/// A GPU-based 2D lighting engine
/// </summary>
public class KryptonEngine : DrawableGameComponent
{
// The Krypton Effect
private string mEffectAssetName;
private Effect mEffect;
private CullMode mCullMode = CullMode.CullCounterClockwiseFace;
// The goods
private List<ShadowHull> mHulls = new List<ShadowHull>();
private List<ILight2D> mLights = new List<ILight2D>();
// 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 = 0f;
private RenderTarget2D mMapBlur;
// Light maps
public RenderTarget2D mMap;
private Color mAmbientColor = new Color(0, 0, 0);
private LightMapSize mLightMapSize = LightMapSize.Full;
/// <summary>
/// Krypton's render helper. It helps render. It also needs to be re-written.
/// </summary>
public KryptonRenderHelper RenderHelper { get; private set; }
/// <summary>
/// Gets or sets a value indicating how Krypton should cull geometry. The default value is CullMode.CounterClockwise
/// </summary>
public CullMode CullMode
{
get { return this.mCullMode; }
set { this.mCullMode = value; }
}
/// <summary>
/// The collection of lights krypton uses to render shadows
/// </summary>
public List<ILight2D> Lights { get { return this.mLights; } }
/// <summary>
/// The collection of hulls krypton uses to render shadows
/// </summary>
public List<ShadowHull> Hulls { get { return this.mHulls; } }
/// <summary>
/// Gets or sets the matrix used to draw the light map. This should match your scene's matrix.
/// </summary>
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;
}
}
}
/// <summary>
/// Gets or sets a value indicating weither or not to use SpriteBatch's matrix when drawing lightmaps
/// </summary>
public bool SpriteBatchCompatablityEnabled
{
get { return this.mSpriteBatchCompatabilityEnabled; }
set { this.mSpriteBatchCompatabilityEnabled = value; }
}
/// <summary>
/// Ambient color of the light map. Lights + AmbientColor = Final
/// </summary>
public Color AmbientColor
{
get { return this.mAmbientColor; }
set { this.mAmbientColor = value; }
}
/// <summary>
/// Gets or sets the value used to determine light map size
/// </summary>
public LightMapSize LightMapSize
{
get { return this.mLightMapSize; }
set
{
if (this.mLightMapSize != value)
{
this.mLightMapSize = value;
this.DisposeRenderTargets();
this.CreateRenderTargets();
}
}
}
/// <summary>
/// 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
/// </summary>
public float Bluriness
{
get { return this.mBluriness; }
set { this.mBluriness = Math.Max(0, value); }
}
/// <summary>
/// Constructs a new instance of krypton
/// </summary>
/// <param name="game">Your game object</param>
/// <param name="effectAssetName">The asset name of Krypton's effect file, which must be included in your content project</param>
public KryptonEngine(Game game, string effectAssetName)
: base(game)
{
this.mEffectAssetName = effectAssetName;
}
/// <summary>
/// Initializes Krpyton, and hooks itself to the graphics device
/// </summary>
public override void Initialize()
{
base.Initialize();
this.GraphicsDevice.DeviceReset += new EventHandler<EventArgs>(GraphicsDevice_DeviceReset);
}
/// <summary>
/// Resets kryptons graphics device resources
/// </summary>
private void GraphicsDevice_DeviceReset(object sender, EventArgs e)
{
this.DisposeRenderTargets();
this.CreateRenderTargets();
}
/// <summary>
/// Load's the graphics related content required to draw light maps
/// </summary>
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<Effect>(this.mEffectAssetName);
this.RenderHelper = new KryptonRenderHelper(this.GraphicsDevice, this.mEffect);
this.CreateRenderTargets();
}
/// <summary>
/// Unload's the graphics content required to draw light maps
/// </summary>
protected override void UnloadContent()
{
this.DisposeRenderTargets();
}
/// <summary>
/// Creates render targets
/// </summary>
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);
}
/// <summary>
/// Disposes of render targets
/// </summary>
private void DisposeRenderTargets()
{
KryptonEngine.TryDispose(this.mMap);
KryptonEngine.TryDispose(this.mMapBlur);
}
/// <summary>
/// Attempts to dispose of disposable objects, and assigns them a null value afterward
/// </summary>
/// <param name="obj"></param>
private static void TryDispose(IDisposable obj)
{
if (obj != null)
{
obj.Dispose();
obj = null;
}
}
/// <summary>
/// Draws the light map to the current render target
/// </summary>
/// <param name="gameTime">N/A - Required</param>
public override void Draw(GameTime gameTime)
{
this.LightMapPresent();
}
/// <summary>
/// Prepares the light map to be drawn (pre-render)
/// </summary>
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, 0);
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);
}
/// <summary>
/// Returns the final, modified matrix used to render the lightmap.
/// </summary>
/// <returns></returns>
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;
}
}
/// <summary>
/// Gets a pixel-space rectangle which contains the light passed in
/// </summary>
/// <param name="light">The light used to create the rectangle</param>
/// <param name="matrix">the WorldViewProjection matrix being used to render</param>
/// <param name="targetSize">The rendertarget's size</param>
/// <returns></returns>
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));
}
/// <summary>
/// Takes a screen-space vector and puts it in to pixel space
/// </summary>
/// <param name="v"></param>
/// <param name="matrix"></param>
/// <param name="targetSize"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Takes a screen-space size vector and converts it to a pixel-space size vector
/// </summary>
/// <param name="v"></param>
/// <param name="matrix"></param>
/// <param name="targetSize"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Retrieves a rasterize state by using the cull mode as a lookup
/// </summary>
/// <param name="cullMode">The cullmode used to lookup the rasterize state</param>
/// <returns></returns>
private static RasterizerState RasterizerStateGetFromCullMode(CullMode cullMode)
{
switch (cullMode)
{
case (CullMode.CullCounterClockwiseFace):
return RasterizerState.CullCounterClockwise;
case (CullMode.CullClockwiseFace):
return RasterizerState.CullClockwise;
default:
return RasterizerState.CullNone;
}
}
/// <summary>
/// Presents the light map to the current render target
/// </summary>
private void LightMapPresent()
{
RenderHelper.DrawTextureToTarget(this.mMap, this.mLightMapSize, BlendTechnique.Multiply);
}
}
}
+476
View File
@@ -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
public static readonly 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<ShadowHullVertex> mShadowHullVertices = new List<ShadowHullVertex>();
private List<Int32> mShadowHullIndicies = new List<Int32>();
public GraphicsDevice GraphicsDevice
{
get { return this.mGraphicsDevice; }
}
public Effect Effect
{
get { return this.mEffect; }
}
public List<ShadowHullVertex> ShadowHullVertices
{
get { return this.mShadowHullVertices; }
}
public List<Int32> 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 = new Color(0, 0, 0, 1-hull.Opacity);
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<VertexPositionColorTexture>(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<VertexPositionColorTexture>(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<ShadowHullVertex>(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<VertexPositionTexture>(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<VertexPositionTexture>(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<VertexPositionTexture>(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);
}
}
}
+89
View File
@@ -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
{
/// <summary>
/// Create a Point Light based on a size.
/// </summary>
/// <param name="device">Your game's GraphicsDevice</param>
/// <param name="size">Maximum Size</param>
/// <returns>Light Texture</returns>
public static Texture2D CreatePointLight(GraphicsDevice device, int size)
{
return CreateConicLight(device, size, MathHelper.TwoPi, 0);
}
/// <summary>
/// Create a Conic Light based on the size, and field of view.
/// </summary>
/// <param name="device">Your game's GraphicsDevice</param>
/// <param name="size">Maximum Size</param>
/// <param name="FOV">Maximum Field of View</param>
/// <returns>Light Texture</returns>
public static Texture2D CreateConicLight(GraphicsDevice device, int size, float FOV)
{
return CreateConicLight(device, size, FOV, 0);
}
/// <summary>
/// Create a Conic Light based on the size, field of view, and near plane distance.
/// </summary>
/// <param name="device">Your game's GraphicsDevice</param>
/// <param name="size">Maximum size</param>
/// <param name="FOV">Maximum Field of View</param>
/// <param name="nearPlaneDistance">Prevents texture from being drawn at this plane distance, originating from the center of light</param>
/// <returns>Light Texture</returns>
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<Color>(Data1D);
return tex;
}
/// <summary>
/// Math helper to determine if integer is a power of two
/// </summary>
/// <param name="x">Integer value</param>
private static bool IsPowerOfTwo(int x)
{
return (x & (x - 1)) == 0;
}
}
}
+17
View File
@@ -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<ShadowHull> hulls);
}
}
+238
View File
@@ -0,0 +1,238 @@
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 enum ShadowType
{
Solid = 1,
Illuminated = 2,
Occluded = 3
};
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;
private ShadowType mShadowType = ShadowType.Solid;
#region Parameters
/// <summary>
/// The light's position
/// </summary>
public Vector2 Position
{
get { return this.mPosition; }
set { this.mPosition = value; }
}
/// <summary>
/// The X coordinate of the light's position
/// </summary>
public float X
{
get { return this.mPosition.X; }
set { this.mPosition.X = value; }
}
/// <summary>
/// The Y coordinate of the light's position
/// </summary>
public float Y
{
get { return this.mPosition.Y; }
set { this.mPosition.Y = value; }
}
/// <summary>
/// The light's angle
/// </summary>
public float Angle
{
get { return this.mAngle; }
set { this.mAngle = value; }
}
/// <summary>
/// The texture used as the base light map, from which shadows will be subtracted
/// </summary>
public Texture2D Texture
{
get { return this.mTexture; }
set { this.mTexture = value; }
}
/// <summary>
/// The color used to tint the light's texture
/// </summary>
public Color Color
{
get { return this.mColor; }
set { this.mColor = value; }
}
/// <summary>
/// The light's maximum radius (or "half width", if you will)
/// </summary>
public float Range
{
get { return this.mRange; }
set { this.mRange = value; }
}
/// <summary>
/// Gets or sets the light's field of view. This value determines the angles at which the light will cease to draw
/// </summary>
public float Fov
{
get { return this.mFov; }
set
{
this.mFov = MathHelper.Clamp(value, 0, MathHelper.TwoPi);
}
}
/// <summary>
/// Gets or sets the light's intensity. Think pixel = (tex * color) ^ (1 / intensity)
/// </summary>
public float Intensity
{
get { return this.mIntensity; }
set { this.mIntensity = MathHelper.Clamp(value, 0.01f, 3f); }
}
/// <summary>
/// Gets or sets a value indicating what type of shadows this light should cast
/// </summary>
public ShadowType ShadowType
{
get { return this.mShadowType; }
set { this.mShadowType = value; }
}
#endregion Parameters
/// <summary>
/// Gets or sets a value indicating weither or not to draw the light
/// </summary>
public bool IsOn
{
get { return this.mIsOn; }
set { this.mIsOn = value; }
}
/// <summary>
/// Draws shadows from the light's position outward
/// </summary>
/// <param name="helper">A render helper for drawing shadows</param>
/// <param name="hulls">The shadow hulls used to draw shadows</param>
public void Draw(KryptonRenderHelper helper, List<ShadowHull> 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);
}
}
// Set the effect and 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));
switch (this.mShadowType)
{
case (ShadowType.Solid):
helper.Effect.CurrentTechnique = helper.Effect.Techniques["PointLight_Shadow_Solid"];
break;
case (ShadowType.Illuminated):
helper.Effect.CurrentTechnique = helper.Effect.Techniques["PointLight_Shadow_Illuminated"];
break;
case (ShadowType.Occluded):
helper.Effect.CurrentTechnique = helper.Effect.Techniques["PointLight_Shadow_Occluded"];
break;
default:
throw new NotImplementedException("Shadow Type does not exist: " + this.mShadowType);
}
foreach (var pass in helper.Effect.CurrentTechnique.Passes)
{
pass.Apply();
helper.BufferDraw();
}
helper.Effect.CurrentTechnique = helper.Effect.Techniques["PointLight_Light"];
foreach (var pass in helper.Effect.CurrentTechnique.Passes)
{
pass.Apply();
helper.DrawClippedFov(this.mPosition, this.mAngle, this.mRange * 2, this.mColor, this.mFov);
}
helper.Effect.CurrentTechnique = helper.Effect.Techniques["ClearTarget_Alpha"];
foreach (var pass in helper.Effect.CurrentTechnique.Passes)
{
pass.Apply();
helper.GraphicsDevice.DrawUserPrimitives<VertexPositionTexture>(PrimitiveType.TriangleStrip, KryptonRenderHelper.UnitQuad, 0, 2);
}
}
/// <summary>
/// Determines if a vector's length is less than a specified value
/// </summary>
/// <param name="offset">Offset</param>
/// <param name="dist">Distance</param>
/// <returns></returns>
private static bool IsInRange(Vector2 offset, float dist)
{
// a^2 + b^2 < c^2 ?
return offset.X * offset.X + offset.Y * offset.Y < dist * dist;
}
/// <summary>
/// Gets the world-space bounds which contain the light
/// </summary>
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;
}
}
}
}
+34
View File
@@ -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")]
+246
View File
@@ -0,0 +1,246 @@
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
{
/// <summary>
/// A hull used for casting shadows from a light source
/// </summary>
public class ShadowHull
{
#region Orientation
/// <summary>
/// The position of the shadow hull
/// </summary>
public Vector2 Position;
/// <summary>
/// The angle of the shadow hull
/// </summary>
public float Angle;
#endregion
#region Shape
/// <summary>
/// The maximum radius in which all of the shadow hull's vertices are contained, originating from the hull's position
/// </summary>
public float MaxRadius;
/// <summary>
/// The vertices comprising the shadow hull
/// </summary>
public ShadowHullPoint[] Points;
/// <summary>
/// The number of vertices comprising the shadow hull
/// </summary>
public int NumPoints;
/// <summary>
/// The indicies used to render the shadow hull
/// </summary>
public Int32[] Indicies;
/// <summary>
/// The number of indicies used to render the shadow hull
/// </summary>
public int NumIndicies;
/// <summary>
/// A value indicating if the hull should cast a shadow
/// </summary>
public bool Visible = true;
/// <summary>
/// A value indicating how much to stretch the hull
/// </summary>
public Vector2 Scale = Vector2.One;
/// <summary>
/// A value indicating how opaque the shadow is, and inversely how much light goes through the hull
/// </summary>
public float Opacity = 1f;
#endregion
private ShadowHull(){}
#region Factory Methods
/// <summary>
/// Creates a rectangular shadow hull
/// </summary>
/// <param name="size">The dimensions of the rectangle</param>
/// <returns>A rectangular shadow hull</returns>
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;
}
/// <summary>
/// Creates a circular shadow hull
/// </summary>
/// <param name="radius">radius of the circle</param>
/// <param name="sides">number of sides the circle will be comprised of</param>
/// <returns>A circular shadow hull</returns>
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;
}
/// <summary>
/// Creates a custom shadow hull based on a series of vertices
/// </summary>
/// <param name="points">The points which the shadow hull will be comprised of</param>
/// <returns>A custom shadow hulll</returns>
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
}
}
+36
View File
@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
namespace Krypton
{
/// <summary>
/// A two dimensional point with normal
/// </summary>
public struct ShadowHullPoint
{
/// <summary>
/// Creates a new Shadow Hull Point
/// </summary>
/// <param name="position">The position of the point</param>
/// <param name="normal">The normal of the side which the point helps represent</param>
public ShadowHullPoint(Vector2 position, Vector2 normal)
{
this.Position = position;
this.Normal = normal;
}
/// <summary>
/// The position of the point
/// </summary>
public Vector2 Position;
/// <summary>
/// The normal of the side of the shadow hull of which the point helps represent
/// </summary>
public Vector2 Normal;
}
}
+60
View File
@@ -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
{
/// <summary>
/// The position of the vertex
/// </summary>
public Vector2 Position;
/// <summary>
/// The normal of the vertex
/// </summary>
public Vector2 Normal;
/// <summary>
/// The color of vertex
/// </summary>
public Color Color;
private static readonly VertexDeclaration mVertexDeclaration;
/// <summary>
///
/// </summary>
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);
}
/// <summary>
///
/// </summary>
/// <param name="position"></param>
/// <param name="normal"></param>
/// <param name="opacity"></param>
public ShadowHullVertex(Vector2 position, Vector2 normal, Color color)
{
this.Position = position;
this.Normal = normal;
this.Color = color;
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

+313
View File
@@ -0,0 +1,313 @@
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
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class KryptonDemoGame : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
KryptonEngine krypton;
private Texture2D mLightTexture;
private int mNumLights = 25;
private int mNumHorzontalHulls = 20;
private int mNumVerticalHulls = 20;
private float mVerticalUnits = 50;
private Light2D mLight2D;
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);
// Create a light we can control
this.mLight2D = new Light2D()
{
Texture = this.mLightTexture,
X = 0,
Y = 0,
Range = 25,
Color = Color.Multiply(Color.CornflowerBlue, 2.0f),
ShadowType = ShadowType.Occluded
};
this.krypton.Lights.Add(this.mLight2D);
}
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 + 5),
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 + 0.5f) * w) / x) - w / 2 + (j % 2 == 0 ? w / x / 2 : 0);
var posY = (((j + 0.5f) * h) / y) - h / 2; // +(i % 2 == 0 ? h / y / 4 : 0);
var hull = ShadowHull.CreateRectangle(Vector2.One*1f);
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;
}
}
var keyboard = Keyboard.GetState();
// Light Position Controls
if (keyboard.IsKeyDown(Keys.Up))
this.mLight2D.Y += t * speed;
if (keyboard.IsKeyDown(Keys.Down))
this.mLight2D.Y -= t * speed;
if (keyboard.IsKeyDown(Keys.Right))
this.mLight2D.X += t * speed;
if (keyboard.IsKeyDown(Keys.Left))
this.mLight2D.X -= t * speed;
// Shadow Type Controls
if (keyboard.IsKeyDown(Keys.D1))
this.mLight2D.ShadowType = ShadowType.Solid;
if (keyboard.IsKeyDown(Keys.D2))
this.mLight2D.ShadowType = ShadowType.Illuminated;
if (keyboard.IsKeyDown(Keys.D3))
this.mLight2D.ShadowType = ShadowType.Occluded;
// Shadow Opacity Controls
if (keyboard.IsKeyDown(Keys.O))
this.krypton.Hulls.ForEach(x => x.Opacity = MathHelper.Clamp(x.Opacity - t, 0, 1));
if (keyboard.IsKeyDown(Keys.P))
this.krypton.Hulls.ForEach(x => x.Opacity = MathHelper.Clamp(x.Opacity + t, 0, 1));
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);
Matrix wvp = world * view * projection;
// 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 = wvp;
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 hulls
this.DebugDrawHulls(true);
// 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);
if (Keyboard.GetState().IsKeyDown(Keys.H))
{
// Draw hulls
this.DebugDrawHulls(false);
}
if (Keyboard.GetState().IsKeyDown(Keys.L))
{
// Draw hulls
this.DebugDrawLights();
}
base.Draw(gameTime);
}
private void DebugDrawHulls(bool drawSolid)
{
this.krypton.RenderHelper.Effect.CurrentTechnique = this.krypton.RenderHelper.Effect.Techniques["DebugDraw"];
this.GraphicsDevice.RasterizerState = new RasterizerState()
{
CullMode = CullMode.None,
FillMode = drawSolid ? FillMode.Solid : FillMode.WireFrame,
};
// 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();
}
}
private void DebugDrawLights()
{
this.krypton.RenderHelper.Effect.CurrentTechnique = this.krypton.RenderHelper.Effect.Techniques["DebugDraw"];
this.GraphicsDevice.RasterizerState = new RasterizerState()
{
CullMode = CullMode.None,
FillMode = FillMode.WireFrame,
};
// Clear the helpers vertices
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();
}
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

+149
View File
@@ -0,0 +1,149 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{E9787BEE-7290-4C74-B919-79DC70AABE87}</ProjectGuid>
<ProjectTypeGuids>{6D335F3A-9D43-41b4-9D22-F6F17C4BE596};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>KryptonTestbed</RootNamespace>
<AssemblyName>KryptonTestbed</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<XnaFrameworkVersion>v4.0</XnaFrameworkVersion>
<XnaPlatform>Windows</XnaPlatform>
<XnaProfile>HiDef</XnaProfile>
<XnaCrossPlatformGroupID>04e8736f-6d19-442f-95e4-08f9b783d054</XnaCrossPlatformGroupID>
<XnaOutputType>Game</XnaOutputType>
<ApplicationIcon>Game.ico</ApplicationIcon>
<Thumbnail>GameThumbnail.png</Thumbnail>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\x86\Debug</OutputPath>
<DefineConstants>DEBUG;TRACE;WINDOWS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoStdLib>true</NoStdLib>
<UseVSHostingProcess>false</UseVSHostingProcess>
<PlatformTarget>x86</PlatformTarget>
<XnaCompressContent>false</XnaCompressContent>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\x86\Release</OutputPath>
<DefineConstants>TRACE;WINDOWS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoStdLib>true</NoStdLib>
<UseVSHostingProcess>false</UseVSHostingProcess>
<PlatformTarget>x86</PlatformTarget>
<XnaCompressContent>true</XnaCompressContent>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Avatar, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
<Reference Include="Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.GamerServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
<Reference Include="Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Input.Touch, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
<Reference Include="Microsoft.Xna.Framework.Net, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
<Reference Include="Microsoft.Xna.Framework.Storage, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
<Reference Include="Microsoft.Xna.Framework.Video, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
<Reference Include="Microsoft.Xna.Framework.Xact, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="mscorlib">
<Private>False</Private>
</Reference>
<Reference Include="System">
<Private>False</Private>
</Reference>
<Reference Include="System.Xml">
<Private>False</Private>
</Reference>
<Reference Include="System.Core">
<Private>False</Private>
</Reference>
<Reference Include="System.Xml.Linq">
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Program.cs" />
<Compile Include="GameKryptonDemo.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Game.ico" />
<Content Include="GameThumbnail.png" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Krypton\Krypton.csproj">
<Project>{B1BFCB2A-C001-4DAC-BA7D-B68BF28757F3}</Project>
<Name>Krypton</Name>
</ProjectReference>
<ProjectReference Include="..\KryptonTestbedContent\KryptonTestbedContent.contentproj">
<Name>KryptonTestbedContent</Name>
<XnaReferenceType>Content</XnaReferenceType>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4 Client Profile %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Xna.Framework.4.0">
<Visible>False</Visible>
<ProductName>Microsoft XNA Framework Redistributable 4.0</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\Microsoft.Xna.GameStudio.targets" />
<!--
To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
+21
View File
@@ -0,0 +1,21 @@
using System;
namespace KryptonTestbed
{
#if WINDOWS || XBOX
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
using (KryptonDemoGame game = new KryptonDemoGame())
{
game.Run();
}
}
}
#endif
}
@@ -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")]
@@ -0,0 +1,438 @@
// ------------------------------------------------------------------------------------------------ //
// ----- 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 = <Texture0>;
AddressU = Clamp;
AddressV = Clamp;
};
sampler2D tex1 = sampler_state
{
Texture = <Texture1>;
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 VertexPositionColorTexture
{
float4 Position : POSITION0;
float4 Color : COLOR0;
float2 TexCoord : TEXCOORD0;
};
struct VertexPositionTexture
{
float4 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
};
struct Color2
{
float4 Color0 : COLOR0;
float4 Color1 : COLOR1;
};
// ------------------------------------------------------------------------------------------------ //
// ----- Vertex Shaders --------------------------------------------------------------------------- //
VertexPositionTexture VS_TextureNoTransform(VertexPositionTexture input)
{
return input;
};
VertexPositionColorTexture VS_ColorTexture(VertexPositionColorTexture input)
{
input.Position = mul(input.Position, Matrix);
return input;
};
VertexPositionColor VS_Hull(ShadowHullVertex input)
{
VertexPositionColor output;
output.Position = mul(input.Position, Matrix);
output.Color = input.Color;
return output;
};
VertexPositionColor VS_Hull_RadialStretch(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;
};
// ------------------------------------------------------------------------------------------------ //
// ----- Pixel Shaders ---------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------ //
// ----- Techniques ------------------------------------------------------------------------------- //
float4 PS_Texture(in float2 texCoord : TEXCOORD0) : COLOR0
{
return tex2D(tex0, texCoord + TexelBias);
};
float4 PS_ColorTexture(in float4 color : COLOR0, in float2 texCoord : TEXCOORD0) : COLOR0
{
return tex2D(tex0, texCoord) * color;
};
float4 PS_LightTexture(VertexPositionColorTexture input) : COLOR0
{
return pow(abs(tex2D(tex0, input.TexCoord)) * input.Color, LightIntensityFactor);
};
float4 PS_Color(in float4 color : COLOR0) : COLOR0
{
return color;
};
float4 PS_White() : COLOR0
{
return float4(1, 1, 1, 1);
};
float4 PS_Black() : COLOR0
{
return float4(0, 0, 0, 1);
};
float4 PS_Debug() : COLOR0
{
return float4(1, 0, 0, 1);
};
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: TextureToTarget ---------------------------------------------------------------
technique TextureToTarget_Add
{
pass Pass1
{
StencilEnable = False;
BlendOp = Add;
SrcBlend = One;
DestBlend = One;
AlphaBlendEnable = True;
CullMode = CCW;
VertexShader = compile vs_2_0 VS_TextureNoTransform();
PixelShader = compile ps_2_0 PS_Texture();
}
};
technique TextureToTarget_Multiply
{
pass Pass1
{
StencilEnable = False;
BlendOp = Add;
SrcBlend = Zero;
DestBlend = SrcColor;
AlphaBlendEnable = True;
CullMode = CCW;
VertexShader = compile vs_2_0 VS_TextureNoTransform();
PixelShader = compile ps_2_0 PS_Texture();
}
};
technique LightTexture
{
pass Pass1
{
StencilEnable = False;
BlendOp = Add;
DestBlend = Zero;
SrcBlend = SrcAlpha;
AlphaBlendEnable = True;
VertexShader = compile vs_2_0 VS_ColorTexture();
PixelShader = compile ps_2_0 PS_LightTexture();
}
};
// ------------------------------------------------------------------------------------------------
// ----- Technique: PointLight_Shadow -------------------------------------------------------------
technique PointLight_Shadow_Solid
{
pass Shadow
{
StencilEnable = False;
ScissorTestEnable = True;
AlphaBlendEnable = True;
BlendOp = Add;
SrcBlend = DestColor;
DestBlend = Zero;
ColorWriteEnable = Alpha;
VertexShader = compile vs_2_0 VS_Hull_RadialStretch();
PixelShader = compile ps_2_0 PS_Color();
}
};
technique PointLight_Shadow_Illuminated
{
pass Shadow
{
StencilEnable = False;
ScissorTestEnable = True;
AlphaBlendEnable = True;
BlendOp = Add;
SrcBlend = DestAlpha;
DestBlend = Zero;
ColorWriteEnable = Alpha;
VertexShader = compile vs_2_0 VS_Hull_RadialStretch();
PixelShader = compile ps_2_0 PS_Color();
}
pass Hull
{
StencilEnable = False;
ScissorTestEnable = True;
AlphaBlendEnable = True;
BlendOp = Add;
SrcBlend = One;
DestBlend = Zero;
ColorWriteEnable = Alpha;
VertexShader = compile vs_2_0 VS_Hull();
PixelShader = compile ps_2_0 PS_White();
}
};
technique PointLight_Shadow_Occluded
{
pass Shadow
{
StencilEnable = True;
StencilFunc = Always;
StencilPass = IncrSat;
StencilFail = Keep;
ScissorTestEnable = True;
AlphaBlendEnable = True;
BlendOp = Add;
SrcBlend = DestAlpha;
DestBlend = Zero;
ColorWriteEnable = Alpha;
VertexShader = compile vs_2_0 VS_Hull_RadialStretch();
PixelShader = compile ps_2_0 PS_Color();
}
pass Hull
{
StencilEnable = True;
StencilFunc = Equal;
StencilRef = 1;
StencilPass = Keep;
ScissorTestEnable = True;
AlphaBlendEnable = True;
BlendOp = Add;
SrcBlend = One;
DestBlend = Zero;
ColorWriteEnable = Alpha;
VertexShader = compile vs_2_0 VS_Hull();
PixelShader = compile ps_2_0 PS_White();
}
};
technique PointLight_Light
{
pass Light
{
StencilEnable = False;
ScissorTestEnable = False;
AlphaBlendEnable = True;
BlendOp = Add;
SrcBlend = DestAlpha;
DestBlend = One;
ColorWriteEnable = Red | Green | Blue;
VertexShader = compile vs_2_0 VS_ColorTexture();
PixelShader = compile ps_2_0 PS_LightTexture();
}
};
technique ClearTarget_Alpha
{
pass Pass1
{
StencilEnable = False;
AlphaBlendEnable = True;
BlendOp = Add;
SrcBlend = One;
DestBlend = One;
ScissorTestEnable = True;
ColorWriteEnable = Red | Green | Blue | Alpha;
VertexShader = compile vs_2_0 VS_TextureNoTransform();
PixelShader = compile ps_2_0 PS_Black();
}
};
// ------------------------------------------------------------------------------------------------
// ----- Technique: Blur --------------------------------------------------------------------------
technique Blur
{
pass HorizontalBlur
{
ScissorTestEnable = False;
StencilEnable = False;
AlphaBlendEnable = False;
CullMode = CCW;
VertexShader = compile vs_2_0 VS_TextureNoTransform();
PixelShader = compile ps_2_0 PS_BlurH();
}
pass VerticalBlur
{
ScissorTestEnable = False;
StencilEnable = False;
AlphaBlendEnable = False;
CullMode = CCW;
VertexShader = compile vs_2_0 VS_TextureNoTransform();
PixelShader = compile ps_2_0 PS_BlurV();
}
}
// ------------------------------------------------------------------------------------------------
// ----- Technique: DebugDraw ---------------------------------------------------------------------
technique DebugDraw
{
pass Solid
{
StencilEnable = False;
AlphaBlendEnable = False;
VertexShader = compile vs_2_0 VS_Hull();
PixelShader = compile ps_2_0 PS_Debug();
}
};
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<ProjectGuid>{EA878F1A-4714-4377-8E6A-4947ACFF386A}</ProjectGuid>
<ProjectTypeGuids>{96E2B04D-8817-42c6-938A-82C39BA4D311};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<XnaFrameworkVersion>v4.0</XnaFrameworkVersion>
<OutputPath>bin\$(Platform)\$(Configuration)</OutputPath>
<ContentRootDirectory>Content</ContentRootDirectory>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup>
<RootNamespace>KryptonTestbedContent</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Include="KryptonEffect.fx">
<Name>KryptonEffect</Name>
<Importer>EffectImporter</Importer>
<Processor>EffectProcessor</Processor>
</Compile>
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline.AudioImporters, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline.EffectImporter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline.FBXImporter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline.TextureImporter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline.VideoImporters, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline.XImporter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\$(XnaFrameworkVersion)\Microsoft.Xna.GameStudio.ContentPipeline.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<TestSettings name="Local" id="aa1589e6-aa53-4011-abe6-96c924b63399" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<Description>These are default test settings for a local test run.</Description>
<Deployment enabled="false" />
<Execution>
<TestTypeSpecific />
<AgentRule name="Execution Agents">
</AgentRule>
</Execution>
</TestSettings>
+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<TestSettings name="Trace and Test Impact" id="37752cef-f8af-48bc-b21d-6eb8bc71c264" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<Description>These are test settings for Trace and Test Impact.</Description>
<Execution>
<TestTypeSpecific />
<AgentRule name="Execution Agents">
</AgentRule>
</Execution>
</TestSettings>