cascaded shadow maps
parent
10f3d9cd98
commit
a55e33f9a9
|
@ -2,22 +2,32 @@ using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
namespace Kav
|
namespace Kav
|
||||||
{
|
{
|
||||||
public struct Camera
|
public struct PerspectiveCamera
|
||||||
{
|
{
|
||||||
public Matrix Transform { get; }
|
public Matrix View { get; }
|
||||||
public Matrix View
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return Matrix.CreateLookAt(Transform.Translation, Transform.Translation + Transform.Forward, Transform.Up);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public Matrix Projection { get; }
|
public Matrix Projection { get; }
|
||||||
|
|
||||||
public Camera(Matrix transform, Matrix projection)
|
public Vector3 Position { get; }
|
||||||
|
public Vector3 Forward { get; }
|
||||||
|
public Vector3 Up { get; }
|
||||||
|
|
||||||
|
public float FieldOfView { get; }
|
||||||
|
public float AspectRatio { get; }
|
||||||
|
public float NearPlane { get; }
|
||||||
|
public float FarPlane { get; }
|
||||||
|
|
||||||
|
public PerspectiveCamera(Vector3 position, Vector3 forward, Vector3 up, float fieldOfView, float aspectRatio, float nearPlane, float farPlane)
|
||||||
{
|
{
|
||||||
Transform = transform;
|
Position = position;
|
||||||
Projection = projection;
|
Forward = forward;
|
||||||
|
Up = up;
|
||||||
|
View = Matrix.CreateLookAt(Position, Position + Forward, Up);
|
||||||
|
|
||||||
|
FieldOfView = fieldOfView;
|
||||||
|
AspectRatio = aspectRatio;
|
||||||
|
NearPlane = nearPlane;
|
||||||
|
FarPlane = farPlane;
|
||||||
|
Projection = Matrix.CreatePerspectiveFieldOfView(FieldOfView, AspectRatio, NearPlane, FarPlane);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,24 @@ namespace Kav
|
||||||
EffectParameter gAlbedoParam;
|
EffectParameter gAlbedoParam;
|
||||||
EffectParameter gNormalParam;
|
EffectParameter gNormalParam;
|
||||||
EffectParameter gMetallicRoughnessParam;
|
EffectParameter gMetallicRoughnessParam;
|
||||||
EffectParameter shadowMapParam;
|
|
||||||
|
EffectParameter shadowMapOneParam;
|
||||||
|
EffectParameter shadowMapTwoParam;
|
||||||
|
EffectParameter shadowMapThreeParam;
|
||||||
|
EffectParameter shadowMapFourParam;
|
||||||
|
|
||||||
|
EffectParameter lightSpaceMatrixOneParam;
|
||||||
|
EffectParameter lightSpaceMatrixTwoParam;
|
||||||
|
EffectParameter lightSpaceMatrixThreeParam;
|
||||||
|
EffectParameter lightSpaceMatrixFourParam;
|
||||||
|
|
||||||
|
EffectParameter viewMatrixParam;
|
||||||
|
EffectParameter cascadeFarPlanesParam;
|
||||||
|
|
||||||
EffectParameter directionalLightColorParam;
|
EffectParameter directionalLightColorParam;
|
||||||
EffectParameter directionalLightDirectionParam;
|
EffectParameter directionalLightDirectionParam;
|
||||||
|
|
||||||
EffectParameter eyePositionParam;
|
EffectParameter eyePositionParam;
|
||||||
EffectParameter lightSpaceMatrixParam;
|
|
||||||
|
|
||||||
PointLightCollection pointLightCollection;
|
PointLightCollection pointLightCollection;
|
||||||
|
|
||||||
|
@ -23,11 +34,22 @@ namespace Kav
|
||||||
public Texture2D GAlbedo { get; set; }
|
public Texture2D GAlbedo { get; set; }
|
||||||
public Texture2D GNormal { get; set; }
|
public Texture2D GNormal { get; set; }
|
||||||
public Texture2D GMetallicRoughness { get; set; }
|
public Texture2D GMetallicRoughness { get; set; }
|
||||||
public Texture2D ShadowMap { get; set; }
|
|
||||||
|
public Texture2D ShadowMapOne { get; set; }
|
||||||
|
public Texture2D ShadowMapTwo { get; set; }
|
||||||
|
public Texture2D ShadowMapThree { get; set; }
|
||||||
|
public Texture2D ShadowMapFour { get; set; }
|
||||||
|
|
||||||
|
public Matrix LightSpaceMatrixOne { get; set; }
|
||||||
|
public Matrix LightSpaceMatrixTwo { get; set; }
|
||||||
|
public Matrix LightSpaceMatrixThree { get; set; }
|
||||||
|
public Matrix LightSpaceMatrixFour { get; set; }
|
||||||
|
|
||||||
|
public Matrix ViewMatrix { get; set; }
|
||||||
|
public float[] CascadeFarPlanes;
|
||||||
|
|
||||||
public Vector3 DirectionalLightColor { get; set; }
|
public Vector3 DirectionalLightColor { get; set; }
|
||||||
public Vector3 DirectionalLightDirection { get; set; }
|
public Vector3 DirectionalLightDirection { get; set; }
|
||||||
public Matrix LightSpaceMatrix { get; set; }
|
|
||||||
|
|
||||||
public Vector3 EyePosition { get; set; }
|
public Vector3 EyePosition { get; set; }
|
||||||
|
|
||||||
|
@ -41,6 +63,8 @@ namespace Kav
|
||||||
|
|
||||||
public DeferredPBREffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.DeferredPBREffect)
|
public DeferredPBREffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.DeferredPBREffect)
|
||||||
{
|
{
|
||||||
|
CascadeFarPlanes = new float[4];
|
||||||
|
|
||||||
CacheEffectParameters();
|
CacheEffectParameters();
|
||||||
|
|
||||||
pointLightCollection = new PointLightCollection(
|
pointLightCollection = new PointLightCollection(
|
||||||
|
@ -82,28 +106,50 @@ namespace Kav
|
||||||
gAlbedoParam.SetValue(GAlbedo);
|
gAlbedoParam.SetValue(GAlbedo);
|
||||||
gNormalParam.SetValue(GNormal);
|
gNormalParam.SetValue(GNormal);
|
||||||
gMetallicRoughnessParam.SetValue(GMetallicRoughness);
|
gMetallicRoughnessParam.SetValue(GMetallicRoughness);
|
||||||
shadowMapParam.SetValue(ShadowMap);
|
|
||||||
|
shadowMapOneParam.SetValue(ShadowMapOne);
|
||||||
|
shadowMapTwoParam.SetValue(ShadowMapTwo);
|
||||||
|
shadowMapThreeParam.SetValue(ShadowMapThree);
|
||||||
|
shadowMapFourParam.SetValue(ShadowMapFour);
|
||||||
|
|
||||||
|
lightSpaceMatrixOneParam.SetValue(LightSpaceMatrixOne);
|
||||||
|
lightSpaceMatrixTwoParam.SetValue(LightSpaceMatrixTwo);
|
||||||
|
lightSpaceMatrixThreeParam.SetValue(LightSpaceMatrixThree);
|
||||||
|
lightSpaceMatrixFourParam.SetValue(LightSpaceMatrixFour);
|
||||||
|
|
||||||
|
viewMatrixParam.SetValue(ViewMatrix);
|
||||||
|
cascadeFarPlanesParam.SetValue(CascadeFarPlanes);
|
||||||
|
|
||||||
directionalLightColorParam.SetValue(DirectionalLightColor);
|
directionalLightColorParam.SetValue(DirectionalLightColor);
|
||||||
directionalLightDirectionParam.SetValue(DirectionalLightDirection);
|
directionalLightDirectionParam.SetValue(DirectionalLightDirection);
|
||||||
|
|
||||||
eyePositionParam.SetValue(EyePosition);
|
eyePositionParam.SetValue(EyePosition);
|
||||||
lightSpaceMatrixParam.SetValue(LightSpaceMatrix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CacheEffectParameters()
|
void CacheEffectParameters()
|
||||||
{
|
{
|
||||||
gPositionParam = Parameters["gPosition"];
|
gPositionParam = Parameters["gPosition"];
|
||||||
gAlbedoParam = Parameters["gAlbedo"];
|
gAlbedoParam = Parameters["gAlbedo"];
|
||||||
gNormalParam = Parameters["gNormal"];
|
gNormalParam = Parameters["gNormal"];
|
||||||
gMetallicRoughnessParam = Parameters["gMetallicRoughness"];
|
gMetallicRoughnessParam = Parameters["gMetallicRoughness"];
|
||||||
shadowMapParam = Parameters["shadowMap"];
|
|
||||||
|
shadowMapOneParam = Parameters["shadowMapOne"];
|
||||||
|
shadowMapTwoParam = Parameters["shadowMapTwo"];
|
||||||
|
shadowMapThreeParam = Parameters["shadowMapThree"];
|
||||||
|
shadowMapFourParam = Parameters["shadowMapFour"];
|
||||||
|
|
||||||
|
lightSpaceMatrixOneParam = Parameters["LightSpaceMatrixOne"];
|
||||||
|
lightSpaceMatrixTwoParam = Parameters["LightSpaceMatrixTwo"];
|
||||||
|
lightSpaceMatrixThreeParam = Parameters["LightSpaceMatrixThree"];
|
||||||
|
lightSpaceMatrixFourParam = Parameters["LightSpaceMatrixFour"];
|
||||||
|
|
||||||
|
viewMatrixParam = Parameters["ViewMatrix"];
|
||||||
|
cascadeFarPlanesParam = Parameters["CascadeFarPlanes"];
|
||||||
|
|
||||||
directionalLightDirectionParam = Parameters["DirectionalLightDirection"];
|
directionalLightDirectionParam = Parameters["DirectionalLightDirection"];
|
||||||
directionalLightColorParam = Parameters["DirectionalLightColor"];
|
directionalLightColorParam = Parameters["DirectionalLightColor"];
|
||||||
lightSpaceMatrixParam = Parameters["LightSpaceMatrix"];
|
|
||||||
|
|
||||||
eyePositionParam = Parameters["EyePosition"];
|
eyePositionParam = Parameters["EyePosition"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
|
@ -2,12 +2,16 @@
|
||||||
|
|
||||||
static const float PI = 3.141592653589793;
|
static const float PI = 3.141592653589793;
|
||||||
static const int MAX_POINT_LIGHTS = 64;
|
static const int MAX_POINT_LIGHTS = 64;
|
||||||
|
static const int NUM_SHADOW_CASCADES = 4;
|
||||||
|
|
||||||
DECLARE_TEXTURE(gPosition, 0);
|
DECLARE_TEXTURE(gPosition, 0);
|
||||||
DECLARE_TEXTURE(gAlbedo, 1);
|
DECLARE_TEXTURE(gAlbedo, 1);
|
||||||
DECLARE_TEXTURE(gNormal, 2);
|
DECLARE_TEXTURE(gNormal, 2);
|
||||||
DECLARE_TEXTURE(gMetallicRoughness, 3);
|
DECLARE_TEXTURE(gMetallicRoughness, 3);
|
||||||
DECLARE_TEXTURE(shadowMap, 4);
|
DECLARE_TEXTURE(shadowMapOne, 4);
|
||||||
|
DECLARE_TEXTURE(shadowMapTwo, 5);
|
||||||
|
DECLARE_TEXTURE(shadowMapThree, 6);
|
||||||
|
DECLARE_TEXTURE(shadowMapFour, 7);
|
||||||
|
|
||||||
BEGIN_CONSTANTS
|
BEGIN_CONSTANTS
|
||||||
|
|
||||||
|
@ -19,9 +23,17 @@ BEGIN_CONSTANTS
|
||||||
float3 DirectionalLightDirection _ps(c129) _cb(c129);
|
float3 DirectionalLightDirection _ps(c129) _cb(c129);
|
||||||
float3 DirectionalLightColor _ps(c130) _cb(c130);
|
float3 DirectionalLightColor _ps(c130) _cb(c130);
|
||||||
|
|
||||||
|
float CascadeFarPlanes[NUM_SHADOW_CASCADES] _ps(c131) _cb(c131);
|
||||||
|
|
||||||
MATRIX_CONSTANTS
|
MATRIX_CONSTANTS
|
||||||
|
|
||||||
float4x4 LightSpaceMatrix _ps(c131) _cb(c131);
|
float4x4 LightSpaceMatrixOne _ps(c135) _cb(c135);
|
||||||
|
float4x4 LightSpaceMatrixTwo _ps(c139) _cb(c139);
|
||||||
|
float4x4 LightSpaceMatrixThree _ps(c143) _cb(c143);
|
||||||
|
float4x4 LightSpaceMatrixFour _ps(c147) _cb(c147);
|
||||||
|
|
||||||
|
// used to select shadow cascade
|
||||||
|
float4x4 ViewMatrix _ps(c151) _cb(c151);
|
||||||
|
|
||||||
END_CONSTANTS
|
END_CONSTANTS
|
||||||
|
|
||||||
|
@ -89,11 +101,44 @@ float GeometrySmith(float3 N, float3 V, float3 L, float roughness)
|
||||||
return ggx1 * ggx2;
|
return ggx1 * ggx2;
|
||||||
}
|
}
|
||||||
|
|
||||||
float ComputeShadow(float4 positionLightSpace, float3 N, float L)
|
float ComputeShadow(float3 positionWorldSpace, float3 N, float L)
|
||||||
{
|
{
|
||||||
float bias = 0.005 * tan(acos(dot(N, L)));
|
float bias = 0.005 * tan(acos(dot(N, L)));
|
||||||
bias = clamp(bias, 0, 0.01);
|
bias = clamp(bias, 0, 0.01);
|
||||||
|
|
||||||
|
float4 positionCameraSpace = mul(float4(positionWorldSpace, 1.0), ViewMatrix);
|
||||||
|
|
||||||
|
int shadowCascadeIndex = 0; // 0 is closest
|
||||||
|
for (int i = 0; i < NUM_SHADOW_CASCADES; i++)
|
||||||
|
{
|
||||||
|
if (positionCameraSpace.z < CascadeFarPlanes[i])
|
||||||
|
{
|
||||||
|
shadowCascadeIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float4x4 lightSpaceMatrix;
|
||||||
|
|
||||||
|
if (shadowCascadeIndex == 0)
|
||||||
|
{
|
||||||
|
lightSpaceMatrix = LightSpaceMatrixOne;
|
||||||
|
}
|
||||||
|
else if (shadowCascadeIndex == 1)
|
||||||
|
{
|
||||||
|
lightSpaceMatrix = LightSpaceMatrixTwo;
|
||||||
|
}
|
||||||
|
else if (shadowCascadeIndex == 2)
|
||||||
|
{
|
||||||
|
lightSpaceMatrix = LightSpaceMatrixThree;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lightSpaceMatrix = LightSpaceMatrixFour;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 positionLightSpace = mul(float4(positionWorldSpace, 1.0), lightSpaceMatrix);
|
||||||
|
|
||||||
// maps to [-1, 1]
|
// maps to [-1, 1]
|
||||||
float3 projectionCoords = positionLightSpace.xyz / positionLightSpace.w;
|
float3 projectionCoords = positionLightSpace.xyz / positionLightSpace.w;
|
||||||
|
|
||||||
|
@ -102,7 +147,24 @@ float ComputeShadow(float4 positionLightSpace, float3 N, float L)
|
||||||
projectionCoords.y = (projectionCoords.y * 0.5) + 0.5;
|
projectionCoords.y = (projectionCoords.y * 0.5) + 0.5;
|
||||||
projectionCoords.y *= -1;
|
projectionCoords.y *= -1;
|
||||||
|
|
||||||
float closestDepth = SAMPLE_TEXTURE(shadowMap, projectionCoords.xy).r;
|
float closestDepth;
|
||||||
|
if (shadowCascadeIndex == 0)
|
||||||
|
{
|
||||||
|
closestDepth = SAMPLE_TEXTURE(shadowMapOne, projectionCoords.xy).r;
|
||||||
|
}
|
||||||
|
else if (shadowCascadeIndex == 1)
|
||||||
|
{
|
||||||
|
closestDepth = SAMPLE_TEXTURE(shadowMapTwo, projectionCoords.xy).r;
|
||||||
|
}
|
||||||
|
else if (shadowCascadeIndex == 2)
|
||||||
|
{
|
||||||
|
closestDepth = SAMPLE_TEXTURE(shadowMapThree, projectionCoords.xy).r;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
closestDepth = SAMPLE_TEXTURE(shadowMapFour, projectionCoords.xy).r;
|
||||||
|
}
|
||||||
|
|
||||||
float currentDepth = projectionCoords.z;
|
float currentDepth = projectionCoords.z;
|
||||||
|
|
||||||
if (currentDepth - bias > closestDepth)
|
if (currentDepth - bias > closestDepth)
|
||||||
|
@ -176,8 +238,7 @@ float4 ComputeColor(
|
||||||
float3 L = normalize(DirectionalLightDirection);
|
float3 L = normalize(DirectionalLightDirection);
|
||||||
float3 radiance = DirectionalLightColor;
|
float3 radiance = DirectionalLightColor;
|
||||||
|
|
||||||
float4 positionLightSpace = mul(float4(worldPosition, 1.0), LightSpaceMatrix);
|
float shadow = ComputeShadow(worldPosition, N, L);
|
||||||
float shadow = ComputeShadow(positionLightSpace, N, L);
|
|
||||||
|
|
||||||
Lo += ComputeLight(L, radiance, F0, V, N, albedo, metallic, roughness, (1.0 - shadow));
|
Lo += ComputeLight(L, radiance, F0, V, N, albedo, metallic, roughness, (1.0 - shadow));
|
||||||
|
|
||||||
|
|
164
Renderer.cs
164
Renderer.cs
|
@ -6,12 +6,15 @@ namespace Kav
|
||||||
{
|
{
|
||||||
public class Renderer
|
public class Renderer
|
||||||
{
|
{
|
||||||
|
private const int MAX_SHADOW_CASCADES = 4;
|
||||||
|
|
||||||
private GraphicsDevice GraphicsDevice { get; }
|
private GraphicsDevice GraphicsDevice { get; }
|
||||||
private int RenderDimensionsX { get; }
|
private int RenderDimensionsX { get; }
|
||||||
private int RenderDimensionsY { get; }
|
private int RenderDimensionsY { get; }
|
||||||
|
|
||||||
private VertexBuffer FullscreenTriangle { get; }
|
private VertexBuffer FullscreenTriangle { get; }
|
||||||
private RenderTarget2D ShadowRenderTarget { get; }
|
private int NumShadowCascades { get; }
|
||||||
|
private RenderTarget2D[] ShadowRenderTargets { get; }
|
||||||
|
|
||||||
private DeferredPBREffect DeferredPBREffect { get; }
|
private DeferredPBREffect DeferredPBREffect { get; }
|
||||||
private SimpleDepthEffect SimpleDepthEffect { get; }
|
private SimpleDepthEffect SimpleDepthEffect { get; }
|
||||||
|
@ -24,22 +27,26 @@ namespace Kav
|
||||||
|
|
||||||
private RenderTargetBinding[] GBuffer { get; }
|
private RenderTargetBinding[] GBuffer { get; }
|
||||||
|
|
||||||
private SpriteBatch SpriteBatch { get; }
|
public Renderer(GraphicsDevice graphicsDevice, int renderDimensionsX, int renderDimensionsY, int numShadowCascades)
|
||||||
|
|
||||||
public Renderer(GraphicsDevice graphicsDevice, int renderDimensionsX, int renderDimensionsY)
|
|
||||||
{
|
{
|
||||||
GraphicsDevice = graphicsDevice;
|
GraphicsDevice = graphicsDevice;
|
||||||
RenderDimensionsX = renderDimensionsX;
|
RenderDimensionsX = renderDimensionsX;
|
||||||
RenderDimensionsY = renderDimensionsY;
|
RenderDimensionsY = renderDimensionsY;
|
||||||
|
|
||||||
ShadowRenderTarget = new RenderTarget2D(
|
NumShadowCascades = (int)MathHelper.Clamp(numShadowCascades, 1, MAX_SHADOW_CASCADES);
|
||||||
GraphicsDevice,
|
ShadowRenderTargets = new RenderTarget2D[numShadowCascades];
|
||||||
1024,
|
|
||||||
1024,
|
for (var i = 0; i < numShadowCascades; i++)
|
||||||
false,
|
{
|
||||||
SurfaceFormat.Single,
|
ShadowRenderTargets[i] = new RenderTarget2D(
|
||||||
DepthFormat.Depth24
|
GraphicsDevice,
|
||||||
);
|
1024,
|
||||||
|
1024,
|
||||||
|
false,
|
||||||
|
SurfaceFormat.Single,
|
||||||
|
DepthFormat.Depth24
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
gPosition = new RenderTarget2D(
|
gPosition = new RenderTarget2D(
|
||||||
GraphicsDevice,
|
GraphicsDevice,
|
||||||
|
@ -100,21 +107,18 @@ namespace Kav
|
||||||
new VertexPositionTexture(new Vector3(3, -1, 0), new Vector2(2, 0))
|
new VertexPositionTexture(new Vector3(3, -1, 0), new Vector2(2, 0))
|
||||||
});
|
});
|
||||||
|
|
||||||
SpriteBatch = new SpriteBatch(GraphicsDevice);
|
|
||||||
|
|
||||||
GraphicsDevice.SetRenderTarget(deferredRenderTarget);
|
GraphicsDevice.SetRenderTarget(deferredRenderTarget);
|
||||||
graphicsDevice.Clear(Color.White);
|
graphicsDevice.Clear(Color.White);
|
||||||
GraphicsDevice.SetRenderTarget(null);
|
GraphicsDevice.SetRenderTarget(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeferredRender(
|
public void DeferredRender(
|
||||||
Camera camera,
|
PerspectiveCamera camera,
|
||||||
IEnumerable<(Model, Matrix)> modelTransforms,
|
IEnumerable<(Model, Matrix)> modelTransforms,
|
||||||
IEnumerable<PointLight> pointLights,
|
IEnumerable<PointLight> pointLights,
|
||||||
DirectionalLight directionalLight,
|
DirectionalLight directionalLight
|
||||||
int numCascades
|
|
||||||
) {
|
) {
|
||||||
ShadowMapRender(camera, modelTransforms, directionalLight, numCascades);
|
ShadowMapRender(camera, modelTransforms, directionalLight);
|
||||||
|
|
||||||
GraphicsDevice.SetRenderTargets(GBuffer);
|
GraphicsDevice.SetRenderTargets(GBuffer);
|
||||||
GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1f, 0);
|
GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1f, 0);
|
||||||
|
@ -161,7 +165,23 @@ namespace Kav
|
||||||
DeferredPBREffect.GAlbedo = gAlbedo;
|
DeferredPBREffect.GAlbedo = gAlbedo;
|
||||||
DeferredPBREffect.GNormal = gNormal;
|
DeferredPBREffect.GNormal = gNormal;
|
||||||
DeferredPBREffect.GMetallicRoughness = gMetallicRoughness;
|
DeferredPBREffect.GMetallicRoughness = gMetallicRoughness;
|
||||||
DeferredPBREffect.ShadowMap = ShadowRenderTarget;
|
|
||||||
|
DeferredPBREffect.ShadowMapOne = ShadowRenderTargets[0];
|
||||||
|
if (NumShadowCascades > 1)
|
||||||
|
{
|
||||||
|
DeferredPBREffect.ShadowMapTwo = ShadowRenderTargets[1];
|
||||||
|
}
|
||||||
|
if (NumShadowCascades > 2)
|
||||||
|
{
|
||||||
|
DeferredPBREffect.ShadowMapThree = ShadowRenderTargets[2];
|
||||||
|
}
|
||||||
|
if (NumShadowCascades > 3)
|
||||||
|
{
|
||||||
|
DeferredPBREffect.ShadowMapFour = ShadowRenderTargets[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
DeferredPBREffect.ViewMatrix = camera.View;
|
||||||
|
|
||||||
DeferredPBREffect.EyePosition = Matrix.Invert(camera.View).Translation;
|
DeferredPBREffect.EyePosition = Matrix.Invert(camera.View).Translation;
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -182,23 +202,15 @@ namespace Kav
|
||||||
GraphicsDevice.SetVertexBuffer(FullscreenTriangle);
|
GraphicsDevice.SetVertexBuffer(FullscreenTriangle);
|
||||||
GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
|
GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, null, null, DeferredPBREffect);
|
|
||||||
// SpriteBatch.Draw(deferredRenderTarget, Vector2.Zero, Color.White);
|
|
||||||
// SpriteBatch.End();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShadowMapRender(
|
public void ShadowMapRender(
|
||||||
Camera camera,
|
PerspectiveCamera camera,
|
||||||
IEnumerable<(Model, Matrix)> modelTransforms,
|
IEnumerable<(Model, Matrix)> modelTransforms,
|
||||||
DirectionalLight directionalLight,
|
DirectionalLight directionalLight
|
||||||
int numCascades
|
|
||||||
) {
|
) {
|
||||||
GraphicsDevice.SetRenderTarget(ShadowRenderTarget);
|
// set up global light matrix
|
||||||
GraphicsDevice.Clear(Color.White);
|
|
||||||
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
|
||||||
GraphicsDevice.BlendState = BlendState.Opaque;
|
|
||||||
|
|
||||||
var right = Vector3.Cross(Vector3.Up, directionalLight.Direction);
|
var right = Vector3.Cross(Vector3.Up, directionalLight.Direction);
|
||||||
var up = Vector3.Cross(directionalLight.Direction, right);
|
var up = Vector3.Cross(directionalLight.Direction, right);
|
||||||
var cameraBoundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
|
var cameraBoundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
|
||||||
|
@ -221,48 +233,39 @@ namespace Kav
|
||||||
BoundingBox lightBox = BoundingBox.CreateFromPoints(frustumCorners);
|
BoundingBox lightBox = BoundingBox.CreateFromPoints(frustumCorners);
|
||||||
Vector3 lightPosition = frustumCenter + directionalLight.Direction * -lightBox.Min.Z;
|
Vector3 lightPosition = frustumCenter + directionalLight.Direction * -lightBox.Min.Z;
|
||||||
|
|
||||||
SimpleDepthEffect.View = Matrix.CreateLookAt(lightPosition, frustumCenter, camera.View.Right);
|
// render the individual shadow maps
|
||||||
SimpleDepthEffect.Projection = Matrix.CreateOrthographicOffCenter(
|
|
||||||
lightBox.Min.X,
|
var frustumDistance = camera.FarPlane - camera.NearPlane;
|
||||||
lightBox.Max.X,
|
var sectionDistance = frustumDistance / NumShadowCascades;
|
||||||
lightBox.Min.Y,
|
|
||||||
lightBox.Max.Y,
|
for (var i = 0; i < NumShadowCascades; i++)
|
||||||
0,
|
|
||||||
lightBox.Max.Z - lightBox.Min.Z
|
|
||||||
);
|
|
||||||
DeferredPBREffect.LightSpaceMatrix = SimpleDepthEffect.View * SimpleDepthEffect.Projection;
|
|
||||||
|
|
||||||
foreach (var (model, transform) in modelTransforms)
|
|
||||||
{
|
{
|
||||||
foreach (var modelMesh in model.Meshes)
|
// divide the view frustum
|
||||||
{
|
var shadowCamera = new PerspectiveCamera(
|
||||||
foreach (var meshPart in modelMesh.MeshParts)
|
camera.Position,
|
||||||
{
|
camera.Forward,
|
||||||
GraphicsDevice.SetVertexBuffer(meshPart.VertexBuffer);
|
camera.Up,
|
||||||
GraphicsDevice.Indices = meshPart.IndexBuffer;
|
camera.FieldOfView,
|
||||||
|
camera.AspectRatio,
|
||||||
SimpleDepthEffect.Model = transform;
|
camera.NearPlane + (i * sectionDistance),
|
||||||
|
camera.NearPlane + ((i + 1) * sectionDistance)
|
||||||
foreach (var pass in SimpleDepthEffect.CurrentTechnique.Passes)
|
);
|
||||||
{
|
|
||||||
pass.Apply();
|
RenderShadowMap(shadowCamera, modelTransforms, directionalLight, i);
|
||||||
|
|
||||||
GraphicsDevice.DrawIndexedPrimitives(
|
|
||||||
PrimitiveType.TriangleList,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
meshPart.VertexBuffer.VertexCount,
|
|
||||||
0,
|
|
||||||
meshPart.Triangles.Length
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderShadowMap(Camera camera, IEnumerable<(Model, Matrix)> modelTransforms, DirectionalLight directionalLight)
|
private void RenderShadowMap(
|
||||||
{
|
PerspectiveCamera camera,
|
||||||
|
IEnumerable<(Model, Matrix)> modelTransforms,
|
||||||
|
DirectionalLight directionalLight,
|
||||||
|
int shadowCascadeIndex
|
||||||
|
) {
|
||||||
|
GraphicsDevice.SetRenderTarget(ShadowRenderTargets[shadowCascadeIndex]);
|
||||||
|
GraphicsDevice.Clear(Color.White);
|
||||||
|
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
||||||
|
GraphicsDevice.BlendState = BlendState.Opaque;
|
||||||
|
|
||||||
var right = Vector3.Cross(Vector3.Up, directionalLight.Direction);
|
var right = Vector3.Cross(Vector3.Up, directionalLight.Direction);
|
||||||
var up = Vector3.Cross(directionalLight.Direction, right);
|
var up = Vector3.Cross(directionalLight.Direction, right);
|
||||||
var cameraBoundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
|
var cameraBoundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
|
||||||
|
@ -295,6 +298,27 @@ namespace Kav
|
||||||
lightBox.Max.Z - lightBox.Min.Z
|
lightBox.Max.Z - lightBox.Min.Z
|
||||||
);
|
);
|
||||||
|
|
||||||
|
var lightSpaceMatrix = SimpleDepthEffect.View * SimpleDepthEffect.Projection;
|
||||||
|
|
||||||
|
if (shadowCascadeIndex == 0)
|
||||||
|
{
|
||||||
|
DeferredPBREffect.LightSpaceMatrixOne = lightSpaceMatrix;
|
||||||
|
}
|
||||||
|
else if (shadowCascadeIndex == 1)
|
||||||
|
{
|
||||||
|
DeferredPBREffect.LightSpaceMatrixTwo = lightSpaceMatrix;
|
||||||
|
}
|
||||||
|
else if (shadowCascadeIndex == 2)
|
||||||
|
{
|
||||||
|
DeferredPBREffect.LightSpaceMatrixThree = lightSpaceMatrix;
|
||||||
|
}
|
||||||
|
else if (shadowCascadeIndex == 3)
|
||||||
|
{
|
||||||
|
DeferredPBREffect.LightSpaceMatrixFour = lightSpaceMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeferredPBREffect.CascadeFarPlanes[shadowCascadeIndex] = camera.FarPlane;
|
||||||
|
|
||||||
foreach (var (model, transform) in modelTransforms)
|
foreach (var (model, transform) in modelTransforms)
|
||||||
{
|
{
|
||||||
foreach (var modelMesh in model.Meshes)
|
foreach (var modelMesh in model.Meshes)
|
||||||
|
@ -325,7 +349,7 @@ namespace Kav
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render(
|
public void Render(
|
||||||
Camera camera,
|
PerspectiveCamera camera,
|
||||||
IEnumerable<(Model, Matrix)> modelTransforms,
|
IEnumerable<(Model, Matrix)> modelTransforms,
|
||||||
IEnumerable<PointLight> pointLights,
|
IEnumerable<PointLight> pointLights,
|
||||||
IEnumerable<DirectionalLight> directionalLights
|
IEnumerable<DirectionalLight> directionalLights
|
||||||
|
|
Loading…
Reference in New Issue