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)); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										190
									
								
								Renderer.cs
								
								
								
								
							
							
						
						
									
										190
									
								
								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,19 +202,66 @@ 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,  | ||||||
|  |             DirectionalLight directionalLight | ||||||
|  |         ) { | ||||||
|  |             // set up global light matrix | ||||||
|  | 
 | ||||||
|  |             var right = Vector3.Cross(Vector3.Up, directionalLight.Direction); | ||||||
|  |             var up = Vector3.Cross(directionalLight.Direction, right); | ||||||
|  |             var cameraBoundingFrustum = new BoundingFrustum(camera.View * camera.Projection); | ||||||
|  |             Vector3[] frustumCorners = cameraBoundingFrustum.GetCorners(); | ||||||
|  | 
 | ||||||
|  |             Vector3 frustumCenter = Vector3.Zero; | ||||||
|  |             for (var i = 0; i < frustumCorners.Length; i++) | ||||||
|  |             { | ||||||
|  |                 frustumCenter += frustumCorners[i]; | ||||||
|  |             } | ||||||
|  |             frustumCenter /= 8f; | ||||||
|  | 
 | ||||||
|  |             var lightView = Matrix.CreateLookAt(frustumCenter, frustumCenter - directionalLight.Direction, camera.View.Right); | ||||||
|  | 
 | ||||||
|  |             for (var i = 0; i < frustumCorners.Length; i++) | ||||||
|  |             { | ||||||
|  |                 frustumCorners[i] = Vector3.Transform(frustumCorners[i], lightView); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             BoundingBox lightBox = BoundingBox.CreateFromPoints(frustumCorners); | ||||||
|  |             Vector3 lightPosition = frustumCenter + directionalLight.Direction * -lightBox.Min.Z; | ||||||
|  |              | ||||||
|  |             // render the individual shadow maps | ||||||
|  | 
 | ||||||
|  |             var frustumDistance = camera.FarPlane - camera.NearPlane; | ||||||
|  |             var sectionDistance = frustumDistance / NumShadowCascades; | ||||||
|  | 
 | ||||||
|  |             for (var i = 0; i < NumShadowCascades; i++) | ||||||
|  |             { | ||||||
|  |                 // divide the view frustum  | ||||||
|  |                 var shadowCamera = new PerspectiveCamera( | ||||||
|  |                     camera.Position, | ||||||
|  |                     camera.Forward, | ||||||
|  |                     camera.Up, | ||||||
|  |                     camera.FieldOfView, | ||||||
|  |                     camera.AspectRatio, | ||||||
|  |                     camera.NearPlane + (i * sectionDistance), | ||||||
|  |                     camera.NearPlane + ((i + 1) * sectionDistance) | ||||||
|  |                 ); | ||||||
|  |                  | ||||||
|  |                 RenderShadowMap(shadowCamera, modelTransforms, directionalLight, i); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void RenderShadowMap( | ||||||
|  |             PerspectiveCamera camera,  | ||||||
|             IEnumerable<(Model, Matrix)> modelTransforms,  |             IEnumerable<(Model, Matrix)> modelTransforms,  | ||||||
|             DirectionalLight directionalLight, |             DirectionalLight directionalLight, | ||||||
|             int numCascades |             int shadowCascadeIndex | ||||||
|         ) { |         ) { | ||||||
|             GraphicsDevice.SetRenderTarget(ShadowRenderTarget); |             GraphicsDevice.SetRenderTarget(ShadowRenderTargets[shadowCascadeIndex]); | ||||||
|             GraphicsDevice.Clear(Color.White); |             GraphicsDevice.Clear(Color.White); | ||||||
|             GraphicsDevice.DepthStencilState = DepthStencilState.Default; |             GraphicsDevice.DepthStencilState = DepthStencilState.Default; | ||||||
|             GraphicsDevice.BlendState = BlendState.Opaque; |             GraphicsDevice.BlendState = BlendState.Opaque; | ||||||
|  | @ -230,70 +297,27 @@ namespace Kav | ||||||
|                 0, |                 0, | ||||||
|                 lightBox.Max.Z - lightBox.Min.Z |                 lightBox.Max.Z - lightBox.Min.Z | ||||||
|             ); |             ); | ||||||
|             DeferredPBREffect.LightSpaceMatrix = SimpleDepthEffect.View * SimpleDepthEffect.Projection; |  | ||||||
| 
 | 
 | ||||||
|             foreach (var (model, transform) in modelTransforms) |             var lightSpaceMatrix = SimpleDepthEffect.View * SimpleDepthEffect.Projection; | ||||||
|  | 
 | ||||||
|  |             if (shadowCascadeIndex == 0) | ||||||
|             { |             { | ||||||
|                 foreach (var modelMesh in model.Meshes) |                 DeferredPBREffect.LightSpaceMatrixOne = lightSpaceMatrix; | ||||||
|                 { |  | ||||||
|                     foreach (var meshPart in modelMesh.MeshParts) |  | ||||||
|                     { |  | ||||||
|                         GraphicsDevice.SetVertexBuffer(meshPart.VertexBuffer); |  | ||||||
|                         GraphicsDevice.Indices = meshPart.IndexBuffer; |  | ||||||
| 
 |  | ||||||
|                         SimpleDepthEffect.Model = transform; |  | ||||||
| 
 |  | ||||||
|                         foreach (var pass in SimpleDepthEffect.CurrentTechnique.Passes) |  | ||||||
|                         { |  | ||||||
|                             pass.Apply(); |  | ||||||
| 
 |  | ||||||
|                             GraphicsDevice.DrawIndexedPrimitives( |  | ||||||
|                                 PrimitiveType.TriangleList, |  | ||||||
|                                 0, |  | ||||||
|                                 0, |  | ||||||
|                                 meshPart.VertexBuffer.VertexCount, |  | ||||||
|                                 0, |  | ||||||
|                                 meshPart.Triangles.Length |  | ||||||
|                             ); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|         } |             else if (shadowCascadeIndex == 1) | ||||||
| 
 |  | ||||||
|         private void RenderShadowMap(Camera camera, IEnumerable<(Model, Matrix)> modelTransforms, DirectionalLight directionalLight) |  | ||||||
|         { |  | ||||||
|             var right = Vector3.Cross(Vector3.Up, directionalLight.Direction); |  | ||||||
|             var up = Vector3.Cross(directionalLight.Direction, right); |  | ||||||
|             var cameraBoundingFrustum = new BoundingFrustum(camera.View * camera.Projection); |  | ||||||
|             Vector3[] frustumCorners = cameraBoundingFrustum.GetCorners(); |  | ||||||
| 
 |  | ||||||
|             Vector3 frustumCenter = Vector3.Zero; |  | ||||||
|             for (var i = 0; i < frustumCorners.Length; i++) |  | ||||||
|             { |             { | ||||||
|                 frustumCenter += frustumCorners[i]; |                 DeferredPBREffect.LightSpaceMatrixTwo = lightSpaceMatrix; | ||||||
|             } |             } | ||||||
|             frustumCenter /= 8f; |             else if (shadowCascadeIndex == 2) | ||||||
| 
 |  | ||||||
|             var lightView = Matrix.CreateLookAt(frustumCenter, frustumCenter - directionalLight.Direction, camera.View.Right); |  | ||||||
| 
 |  | ||||||
|             for (var i = 0; i < frustumCorners.Length; i++) |  | ||||||
|             { |             { | ||||||
|                 frustumCorners[i] = Vector3.Transform(frustumCorners[i], lightView); |                 DeferredPBREffect.LightSpaceMatrixThree = lightSpaceMatrix; | ||||||
|  |             } | ||||||
|  |             else if (shadowCascadeIndex == 3) | ||||||
|  |             { | ||||||
|  |                 DeferredPBREffect.LightSpaceMatrixFour = lightSpaceMatrix; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             BoundingBox lightBox = BoundingBox.CreateFromPoints(frustumCorners); |             DeferredPBREffect.CascadeFarPlanes[shadowCascadeIndex] = camera.FarPlane; | ||||||
|             Vector3 lightPosition = frustumCenter + directionalLight.Direction * -lightBox.Min.Z; |  | ||||||
|              |  | ||||||
|             SimpleDepthEffect.View = Matrix.CreateLookAt(lightPosition, frustumCenter, camera.View.Right); |  | ||||||
|             SimpleDepthEffect.Projection = Matrix.CreateOrthographicOffCenter( |  | ||||||
|                 lightBox.Min.X, |  | ||||||
|                 lightBox.Max.X, |  | ||||||
|                 lightBox.Min.Y, |  | ||||||
|                 lightBox.Max.Y, |  | ||||||
|                 0, |  | ||||||
|                 lightBox.Max.Z - lightBox.Min.Z |  | ||||||
|             ); |  | ||||||
| 
 | 
 | ||||||
|             foreach (var (model, transform) in modelTransforms) |             foreach (var (model, transform) in modelTransforms) | ||||||
|             { |             { | ||||||
|  | @ -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