diff --git a/Effects/DeferredPBR_PointLightEffect.cs b/Effects/DeferredPBR_PointLightEffect.cs
index 82a73ea..b792ae0 100644
--- a/Effects/DeferredPBR_PointLightEffect.cs
+++ b/Effects/DeferredPBR_PointLightEffect.cs
@@ -18,6 +18,8 @@ namespace Kav
EffectParameter farPlaneParam;
+ EffectParameter worldViewProjectionParam;
+
public Texture2D GPosition { get; set; }
public Texture2D GAlbedo { get; set; }
public Texture2D GNormal { get; set; }
@@ -31,6 +33,42 @@ namespace Kav
public float FarPlane { get; set; }
+ Matrix world = Matrix.Identity;
+ Matrix view = Matrix.Identity;
+ Matrix projection = Matrix.Identity;
+
+ EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
+
+ public Matrix World
+ {
+ get { return world; }
+ set
+ {
+ world = value;
+ dirtyFlags |= EffectDirtyFlags.WorldViewProj;
+ }
+ }
+
+ public Matrix View
+ {
+ get { return view; }
+ set
+ {
+ view = value;
+ dirtyFlags |= EffectDirtyFlags.WorldViewProj;
+ }
+ }
+
+ public Matrix Projection
+ {
+ get { return projection; }
+ set
+ {
+ projection = value;
+ dirtyFlags |= EffectDirtyFlags.WorldViewProj;
+ }
+ }
+
public DeferredPBR_PointLightEffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.DeferredPBR_PointLightEffect)
{
CacheEffectParameters();
@@ -73,6 +111,13 @@ namespace Kav
pointLightColorParam.SetValue(PointLightColor);
farPlaneParam.SetValue(FarPlane);
+
+ if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0)
+ {
+ worldViewProjectionParam.SetValue(world * view * projection);
+
+ dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
+ }
}
void CacheEffectParameters()
@@ -89,6 +134,8 @@ namespace Kav
pointLightColorParam = Parameters["PointLightColor"];
farPlaneParam = Parameters["FarPlane"];
+
+ worldViewProjectionParam = Parameters["WorldViewProjection"];
}
}
}
diff --git a/Effects/FXB/DeferredPBR_PointLightEffect.fxb b/Effects/FXB/DeferredPBR_PointLightEffect.fxb
index 9511784..a05cd21 100644
--- a/Effects/FXB/DeferredPBR_PointLightEffect.fxb
+++ b/Effects/FXB/DeferredPBR_PointLightEffect.fxb
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:033598dc2f22c2766a8b0d46215e5a9764b5445a520d67bc68f1566dbdd15035
-size 3740
+oid sha256:9a30fb7bc8d5af4490f415509711762aa45ee8d5ef4c67d01eb8ae6af10778a0
+size 4076
diff --git a/Effects/HLSL/DeferredPBR_PointLightEffect.fx b/Effects/HLSL/DeferredPBR_PointLightEffect.fx
index d6e1933..0195594 100644
--- a/Effects/HLSL/DeferredPBR_PointLightEffect.fx
+++ b/Effects/HLSL/DeferredPBR_PointLightEffect.fx
@@ -1,3 +1,5 @@
+// Assumes you are drawing a sphere!!
+
#include "Macros.fxh" //from FNA
#include "Lighting.fxh"
#include "Shadow.fxh"
@@ -19,26 +21,27 @@ BEGIN_CONSTANTS
MATRIX_CONSTANTS
+ float4x4 WorldViewProjection _vs(c0) _cb(c4);
+
END_CONSTANTS
struct VertexInput
{
float4 Position : POSITION;
- float2 TexCoord : TEXCOORD;
};
struct PixelInput
{
float4 Position : SV_POSITION;
- float2 TexCoord : TEXCOORD0;
+ float4 ScreenPosition : TEXCOORD0;
};
PixelInput main_vs(VertexInput input)
{
PixelInput output;
- output.Position = input.Position;
- output.TexCoord = input.TexCoord;
+ output.Position = mul(input.Position, WorldViewProjection);
+ output.ScreenPosition = output.Position;
return output;
}
@@ -73,10 +76,13 @@ float4 ComputeColor(
float4 main_ps(PixelInput input) : SV_TARGET0
{
- float3 worldPosition = SAMPLE_TEXTURE(gPosition, input.TexCoord).rgb;
- float3 normal = SAMPLE_TEXTURE(gNormal, input.TexCoord).xyz;
- float3 albedo = SAMPLE_TEXTURE(gAlbedo, input.TexCoord).rgb;
- float2 metallicRoughness = SAMPLE_TEXTURE(gMetallicRoughness, input.TexCoord).rg;
+ input.ScreenPosition.xy /= input.ScreenPosition.w;
+ float2 texCoord = 0.5f * float2(input.ScreenPosition.x,-input.ScreenPosition.y) + 0.5f;
+
+ float3 worldPosition = SAMPLE_TEXTURE(gPosition, texCoord).rgb;
+ float3 normal = SAMPLE_TEXTURE(gNormal, texCoord).xyz;
+ float3 albedo = SAMPLE_TEXTURE(gAlbedo, texCoord).rgb;
+ float2 metallicRoughness = SAMPLE_TEXTURE(gMetallicRoughness, texCoord).rg;
return ComputeColor(
worldPosition,
diff --git a/Kav.Core.csproj b/Kav.Core.csproj
index 541feb0..676e7c2 100644
--- a/Kav.Core.csproj
+++ b/Kav.Core.csproj
@@ -64,6 +64,9 @@
Kav.Resources.UnitCube.glb
+
+ Kav.Resources.UnitSphere.glb
+
diff --git a/Kav.Framework.csproj b/Kav.Framework.csproj
index 1cf665d..2263772 100644
--- a/Kav.Framework.csproj
+++ b/Kav.Framework.csproj
@@ -64,6 +64,9 @@
Kav.Resources.UnitCube.glb
+
+ Kav.Resources.UnitSphere.glb
+
diff --git a/Lights/PointLight.cs b/Lights/PointLight.cs
index 6d3fb90..50f32ca 100644
--- a/Lights/PointLight.cs
+++ b/Lights/PointLight.cs
@@ -4,15 +4,23 @@ namespace Kav
{
public struct PointLight
{
+ public static double ATTENUATION_EPSILON = 0.1;
+
public Vector3 Position { get; }
public Color Color { get; }
public float Intensity { get; }
+ public float EffectiveRadius { get; }
+ public BoundingSphere BoundingSphere { get; }
+
public PointLight(Vector3 position, Color color, float intensity = 1f)
{
Position = position;
Color = color;
Intensity = intensity;
+
+ EffectiveRadius = (float) System.Math.Sqrt(Intensity);
+ BoundingSphere = new BoundingSphere(position, EffectiveRadius);
}
}
}
diff --git a/Models/UnitSphere.glb b/Models/UnitSphere.glb
new file mode 100644
index 0000000..b495e77
Binary files /dev/null and b/Models/UnitSphere.glb differ
diff --git a/Renderer.cs b/Renderer.cs
index 59da550..594f0fb 100644
--- a/Renderer.cs
+++ b/Renderer.cs
@@ -26,8 +26,9 @@ namespace Kav
private Effect ToneMapEffect { get; }
private SkyboxEffect SkyboxEffect { get; }
private DiffuseLitSpriteEffect DiffuseLitSpriteEffect { get; }
-
+
private Kav.Model UnitCube { get; }
+ private Kav.Model UnitSphere { get; }
public Renderer(
GraphicsDevice graphicsDevice
@@ -61,6 +62,11 @@ namespace Kav
GraphicsDevice,
Smuggler.Importer.ImportGLB(GraphicsDevice, new MemoryStream(Resources.UnitCubeModel))
);
+
+ UnitSphere = Kav.ModelLoader.Load(
+ graphicsDevice,
+ Smuggler.Importer.ImportGLB(graphicsDevice, new MemoryStream(Resources.UnitSphereModel))
+ );
}
public static (T[], DynamicVertexBuffer) CreateInstanceVertexBuffer(
@@ -461,7 +467,16 @@ namespace Kav
PointLight pointLight
) {
GraphicsDevice.SetRenderTarget(renderTarget);
- GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
+ if (Vector3.Distance(camera.Position, pointLight.Position) < pointLight.EffectiveRadius)
+ {
+ GraphicsDevice.RasterizerState = RasterizerState.CullClockwise;
+ }
+ else
+ {
+ GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
+ }
+
+ GraphicsDevice.DepthStencilState = DepthStencilState.None;
GraphicsDevice.BlendState = BlendState.Additive;
DeferredPointLightEffect.GPosition = gPosition;
@@ -478,7 +493,17 @@ namespace Kav
DeferredPointLightEffect.FarPlane = 25f; // FIXME: magic value
- RenderFullscreenEffect(DeferredPointLightEffect);
+ DeferredPointLightEffect.World =
+ Matrix.CreateScale(pointLight.EffectiveRadius) *
+ Matrix.CreateTranslation(pointLight.Position);
+ DeferredPointLightEffect.View = camera.View;
+ DeferredPointLightEffect.Projection = camera.Projection;
+
+ RenderIndexed(
+ GraphicsDevice,
+ UnitSphere.Meshes[0].MeshParts[0],
+ DeferredPointLightEffect
+ );
}
public void RenderDirectionalLight(
@@ -492,6 +517,7 @@ namespace Kav
DirectionalLight directionalLight
) {
GraphicsDevice.SetRenderTarget(renderTarget);
+ GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
GraphicsDevice.BlendState = BlendState.Additive;
diff --git a/Resources.cs b/Resources.cs
index ae53a3d..05d2a1b 100644
--- a/Resources.cs
+++ b/Resources.cs
@@ -195,6 +195,18 @@ namespace Kav
}
}
+ public static byte[] UnitSphereModel
+ {
+ get
+ {
+ if (unitSphereModel == null)
+ {
+ unitSphereModel = GetResource("UnitSphere.glb");
+ }
+ return unitSphereModel;
+ }
+ }
+
private static byte[] ambientLightEffect;
private static byte[] pointLightEffect;
private static byte[] directionalLightEffect;
@@ -212,6 +224,7 @@ namespace Kav
private static byte[] paletteCrushEffect;
private static byte[] unitCubeModel;
+ private static byte[] unitSphereModel;
private static byte[] GetResource(string name)
{