toon shadows
							parent
							
								
									632f0a5b06
								
							
						
					
					
						commit
						d370d4e2e4
					
				|  | @ -0,0 +1,14 @@ | |||
| using Microsoft.Xna.Framework; | ||||
| 
 | ||||
| namespace Kav | ||||
| { | ||||
|     public interface ShadowCascadeEffect | ||||
|     { | ||||
|         Matrix LightSpaceMatrixOne { get; set; } | ||||
|         Matrix LightSpaceMatrixTwo { get; set; } | ||||
|         Matrix LightSpaceMatrixThree { get; set; } | ||||
|         Matrix LightSpaceMatrixFour { get; set; } | ||||
| 
 | ||||
|         float[] CascadeFarPlanes { get; } | ||||
|     } | ||||
| } | ||||
|  | @ -3,7 +3,7 @@ using Microsoft.Xna.Framework.Graphics; | |||
| 
 | ||||
| namespace Kav | ||||
| { | ||||
|     public class DeferredPBR_DirectionalLightEffect : Effect | ||||
|     public class DeferredPBR_DirectionalLightEffect : Effect, ShadowCascadeEffect | ||||
|     { | ||||
|         EffectParameter gPositionParam; | ||||
|         EffectParameter gAlbedoParam; | ||||
|  | @ -46,7 +46,7 @@ namespace Kav | |||
|         public Vector3 DirectionalLightDirection { get; set; } | ||||
|         public Vector3 DirectionalLightColor { get; set; } | ||||
| 
 | ||||
|         public readonly float[] CascadeFarPlanes; | ||||
|         public float[] CascadeFarPlanes { get; } | ||||
| 
 | ||||
|         public int ShadowMapSize { get; set; } | ||||
| 
 | ||||
|  | @ -147,7 +147,6 @@ namespace Kav | |||
|             directionalLightColorParam     = Parameters["DirectionalLightColor"]; | ||||
| 
 | ||||
|             cascadeFarPlanesParam          = Parameters["CascadeFarPlanes"]; | ||||
| 
 | ||||
|             shadowMapSizeParam             = Parameters["ShadowMapSize"]; | ||||
| 
 | ||||
|             lightSpaceMatrixOneParam       = Parameters["LightSpaceMatrixOne"]; | ||||
|  |  | |||
|  | @ -3,30 +3,61 @@ using Microsoft.Xna.Framework.Graphics; | |||
| 
 | ||||
| namespace Kav | ||||
| { | ||||
|     public class Deferred_ToonEffect : Effect | ||||
|     public class Deferred_ToonEffect : Effect, ShadowCascadeEffect | ||||
|     { | ||||
|         EffectParameter gPositionParam; | ||||
|         EffectParameter gAlbedoParam; | ||||
|         EffectParameter gNormalParam; | ||||
| 
 | ||||
|         EffectParameter shadowMapOneParam; | ||||
|         EffectParameter shadowMapTwoParam; | ||||
|         EffectParameter shadowMapThreeParam; | ||||
|         EffectParameter shadowMapFourParam; | ||||
| 
 | ||||
|         EffectParameter eyePositionParam; | ||||
|         EffectParameter directionalLightDirectionParam; | ||||
|         EffectParameter directionalLightColorParam; | ||||
| 
 | ||||
|         EffectParameter softnessParam; | ||||
| 
 | ||||
|         EffectParameter cascadeFarPlanesParam; | ||||
|         EffectParameter shadowMapSizeParam; | ||||
| 
 | ||||
|         EffectParameter lightSpaceMatrixOneParam; | ||||
|         EffectParameter lightSpaceMatrixTwoParam; | ||||
|         EffectParameter lightSpaceMatrixThreeParam; | ||||
|         EffectParameter lightSpaceMatrixFourParam; | ||||
| 
 | ||||
|         EffectParameter viewMatrixParam; | ||||
| 
 | ||||
|         public Texture2D GPosition { get; set; } | ||||
|         public Texture2D GAlbedo { get; set; } | ||||
|         public Texture2D GNormal { get; set; } | ||||
| 
 | ||||
|         public Texture2D ShadowMapOne { get; set; } | ||||
|         public Texture2D ShadowMapTwo { get; set; } | ||||
|         public Texture2D ShadowMapThree { get; set; } | ||||
|         public Texture2D ShadowMapFour { get; set; } | ||||
| 
 | ||||
|         public Vector3 EyePosition { get; set; } | ||||
|         public Vector3 DirectionalLightDirection { get; set; } | ||||
|         public Vector3 DirectionalLightColor { get; set; } | ||||
| 
 | ||||
|         public float Softness { get; set; } | ||||
| 
 | ||||
|         public float[] CascadeFarPlanes { get; } | ||||
|         public float ShadowMapSize { 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 Deferred_ToonEffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.Deferred_ToonEffect) | ||||
|         { | ||||
|             CascadeFarPlanes = new float[4]; | ||||
|             CacheEffectParameters();    | ||||
|         } | ||||
| 
 | ||||
|  | @ -36,11 +67,26 @@ namespace Kav | |||
|             gAlbedoParam.SetValue(GAlbedo); | ||||
|             gNormalParam.SetValue(GNormal); | ||||
| 
 | ||||
|             shadowMapOneParam.SetValue(ShadowMapOne); | ||||
|             shadowMapTwoParam.SetValue(ShadowMapTwo); | ||||
|             shadowMapThreeParam.SetValue(ShadowMapThree); | ||||
|             shadowMapFourParam.SetValue(ShadowMapFour); | ||||
| 
 | ||||
|             eyePositionParam.SetValue(EyePosition); | ||||
|             directionalLightDirectionParam.SetValue(DirectionalLightDirection); | ||||
|             directionalLightColorParam.SetValue(DirectionalLightColor); | ||||
| 
 | ||||
|             softnessParam.SetValue(Softness); | ||||
| 
 | ||||
|             cascadeFarPlanesParam.SetValue(CascadeFarPlanes); | ||||
|             shadowMapSizeParam.SetValue(ShadowMapSize); | ||||
| 
 | ||||
|             lightSpaceMatrixOneParam.SetValue(LightSpaceMatrixOne); | ||||
|             lightSpaceMatrixTwoParam.SetValue(LightSpaceMatrixTwo); | ||||
|             lightSpaceMatrixThreeParam.SetValue(LightSpaceMatrixThree); | ||||
|             lightSpaceMatrixFourParam.SetValue(LightSpaceMatrixFour); | ||||
| 
 | ||||
|             viewMatrixParam.SetValue(ViewMatrix); | ||||
|         } | ||||
| 
 | ||||
|         void CacheEffectParameters() | ||||
|  | @ -49,11 +95,26 @@ namespace Kav | |||
|             gAlbedoParam                   = Parameters["gAlbedo"]; | ||||
|             gNormalParam                   = Parameters["gNormal"]; | ||||
| 
 | ||||
|             shadowMapOneParam              = Parameters["shadowMapOne"]; | ||||
|             shadowMapTwoParam              = Parameters["shadowMapTwo"]; | ||||
|             shadowMapThreeParam            = Parameters["shadowMapThree"]; | ||||
|             shadowMapFourParam             = Parameters["shadowMapFour"]; | ||||
| 
 | ||||
|             eyePositionParam               = Parameters["EyePosition"]; | ||||
|             directionalLightDirectionParam = Parameters["DirectionalLightDirection"]; | ||||
|             directionalLightColorParam     = Parameters["DirectionalLightColor"]; | ||||
| 
 | ||||
|             softnessParam                  = Parameters["Softness"]; | ||||
| 
 | ||||
|             cascadeFarPlanesParam          = Parameters["CascadeFarPlanes"]; | ||||
|             shadowMapSizeParam             = Parameters["ShadowMapSize"]; | ||||
| 
 | ||||
|             lightSpaceMatrixOneParam       = Parameters["LightSpaceMatrixOne"]; | ||||
|             lightSpaceMatrixTwoParam       = Parameters["LightSpaceMatrixTwo"]; | ||||
|             lightSpaceMatrixThreeParam     = Parameters["LightSpaceMatrixThree"]; | ||||
|             lightSpaceMatrixFourParam      = Parameters["LightSpaceMatrixFour"]; | ||||
| 
 | ||||
|             viewMatrixParam                = Parameters["ViewMatrix"]; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
							
								
								
									
										
											BIN
										
									
								
								Effects/FXB/Deferred_ToonEffect.fxb (Stored with Git LFS)
								
								
								
								
							
							
						
						
									
										
											BIN
										
									
								
								Effects/FXB/Deferred_ToonEffect.fxb (Stored with Git LFS)
								
								
								
								
							
										
											Binary file not shown.
										
									
								
							|  | @ -1,17 +1,37 @@ | |||
| #include "Macros.fxh" | ||||
| #include "Shadow.fxh" | ||||
| 
 | ||||
| static const int NUM_SHADOW_CASCADES = 4; | ||||
| 
 | ||||
| DECLARE_TEXTURE(gPosition, 0); | ||||
| DECLARE_TEXTURE(gAlbedo, 1); | ||||
| DECLARE_TEXTURE(gNormal, 2); | ||||
| DECLARE_TEXTURE(shadowMapOne, 4); | ||||
| DECLARE_TEXTURE(shadowMapTwo, 5); | ||||
| DECLARE_TEXTURE(shadowMapThree, 6); | ||||
| DECLARE_TEXTURE(shadowMapFour, 7); | ||||
| 
 | ||||
| BEGIN_CONSTANTS | ||||
| 
 | ||||
| float3 EyePosition                  _ps(c0)     _cb(c0); | ||||
| float3 EyePosition                           _ps(c0)     _cb(c0); | ||||
| 
 | ||||
| float3 DirectionalLightDirection    _ps(c1)     _cb(c1); | ||||
| float3 DirectionalLightColor        _ps(c2)     _cb(c2); | ||||
| float3 DirectionalLightDirection             _ps(c1)     _cb(c1); | ||||
| float3 DirectionalLightColor                 _ps(c2)     _cb(c2); | ||||
| 
 | ||||
| float Softness                      _ps(c3)     _cb(c3); | ||||
| float Softness                               _ps(c3)     _cb(c3); | ||||
| 
 | ||||
| float CascadeFarPlanes[NUM_SHADOW_CASCADES]  _ps(c4)     _cb(c4); | ||||
| 
 | ||||
| float ShadowMapSize                          _ps(c8)     _cb(c8); | ||||
| 
 | ||||
| MATRIX_CONSTANTS | ||||
| 
 | ||||
| float4x4 LightSpaceMatrixOne                 _ps(c9)     _cb(c9); | ||||
| float4x4 LightSpaceMatrixTwo                 _ps(c13)    _cb(c13); | ||||
| float4x4 LightSpaceMatrixThree               _ps(c17)    _cb(c17); | ||||
| float4x4 LightSpaceMatrixFour                _ps(c21)    _cb(c21); | ||||
| 
 | ||||
| float4x4 ViewMatrix                          _ps(c25)    _cb(c25); | ||||
| 
 | ||||
| END_CONSTANTS | ||||
| 
 | ||||
|  | @ -37,6 +57,88 @@ PixelInput main_vs(VertexInput input) | |||
|     return output; | ||||
| } | ||||
| 
 | ||||
| float ComputeShadow(float3 positionWorldSpace, float3 N, float3 L) | ||||
| { | ||||
|     float4 positionCameraSpace = mul(float4(positionWorldSpace, 1.0), ViewMatrix); | ||||
| 
 | ||||
|     int shadowCascadeIndex = 0; // 0 is closest | ||||
|     for (int i = 0; i < NUM_SHADOW_CASCADES; i++) | ||||
|     { | ||||
|         if (abs(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; | ||||
|     } | ||||
| 
 | ||||
|     // PCF + Poisson soft shadows | ||||
| 
 | ||||
|     if (shadowCascadeIndex == 0) | ||||
|     { | ||||
|         return PoissonShadow( | ||||
|             positionWorldSpace, | ||||
|             N, | ||||
|             L, | ||||
|             lightSpaceMatrix, | ||||
|             SAMPLER(shadowMapOne), | ||||
|             ShadowMapSize | ||||
|         ); | ||||
|     } | ||||
|     else if (shadowCascadeIndex == 1) | ||||
|     { | ||||
|         return PoissonShadow( | ||||
|             positionWorldSpace, | ||||
|             N, | ||||
|             L, | ||||
|             lightSpaceMatrix, | ||||
|             SAMPLER(shadowMapTwo), | ||||
|             ShadowMapSize | ||||
|         ); | ||||
|     } | ||||
|     else if (shadowCascadeIndex == 2) | ||||
|     { | ||||
|         return PoissonShadow( | ||||
|             positionWorldSpace, | ||||
|             N, | ||||
|             L, | ||||
|             lightSpaceMatrix, | ||||
|             SAMPLER(shadowMapThree), | ||||
|             ShadowMapSize | ||||
|         ); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         return PoissonShadow( | ||||
|             positionWorldSpace, | ||||
|             N, | ||||
|             L, | ||||
|             lightSpaceMatrix, | ||||
|             SAMPLER(shadowMapFour), | ||||
|             ShadowMapSize | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // FIXME: organize this | ||||
| float4 main_ps(PixelInput input) : SV_TARGET0 | ||||
| { | ||||
|     float3 worldPosition = SAMPLE_TEXTURE(gPosition, input.TexCoord).rgb; | ||||
|  | @ -76,7 +178,8 @@ float4 main_ps(PixelInput input) : SV_TARGET0 | |||
|     rimIntensity = smoothstep(rimAmount - 0.01, rimAmount + 0.01, rimIntensity); | ||||
|     float3 rim = rimIntensity * rimColor; | ||||
| 
 | ||||
|     float3 color = albedo * (light + specular + rim); | ||||
|     float shadow = ComputeShadow(worldPosition, N, L); | ||||
|     float3 color = albedo * (light + specular + rim) * shadow; | ||||
| 
 | ||||
|     return float4(color, 1.0); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										96
									
								
								Renderer.cs
								
								
								
								
							
							
						
						
									
										96
									
								
								Renderer.cs
								
								
								
								
							|  | @ -195,11 +195,7 @@ namespace Kav | |||
|             GraphicsDevice.Clear(Color.Black); | ||||
| 
 | ||||
|             AmbientLightRender(ambientLight); | ||||
| 
 | ||||
|             Deferred_ToonEffect.GPosition = gPosition; | ||||
|             Deferred_ToonEffect.GAlbedo = gAlbedo; | ||||
|             Deferred_ToonEffect.GNormal = gNormal; | ||||
|             DirectionalLightToonRender(camera, directionalLight); | ||||
|             DirectionalLightToonRender(camera, modelTransforms, directionalLight); | ||||
| 
 | ||||
|             GraphicsDevice.SetRenderTarget(null); | ||||
|             GraphicsDevice.Clear(Color.Black); | ||||
|  | @ -298,28 +294,7 @@ namespace Kav | |||
|             IEnumerable<(Model, Matrix)> modelTransforms, | ||||
|             DirectionalLight directionalLight | ||||
|         ) { | ||||
|             // render the individual shadow cascades | ||||
|             var previousFarPlane = camera.NearPlane; | ||||
|             for (var i = 0; i < NumShadowCascades; i++) | ||||
|             { | ||||
|                 var farPlane = camera.FarPlane / (MathHelper.Max((NumShadowCascades - i - 1) * 2f, 1f)); | ||||
| 
 | ||||
|                 // divide the view frustum  | ||||
|                 var shadowCamera = new PerspectiveCamera( | ||||
|                     camera.Position, | ||||
|                     camera.Forward, | ||||
|                     camera.Up, | ||||
|                     camera.FieldOfView, | ||||
|                     camera.AspectRatio, | ||||
|                     previousFarPlane, | ||||
|                     farPlane | ||||
|                 ); | ||||
|                  | ||||
|                 // TODO: This is tightly coupled to the effect and it sucks | ||||
|                 RenderShadowMap(shadowCamera, modelTransforms, directionalLight, i); | ||||
| 
 | ||||
|                 previousFarPlane = farPlane; | ||||
|             } | ||||
|             RenderShadows(camera, modelTransforms, directionalLight, DeferredDirectionalLightEffect); | ||||
| 
 | ||||
|             DeferredDirectionalLightEffect.GPosition = gPosition; | ||||
|             DeferredDirectionalLightEffect.GAlbedo = gAlbedo; | ||||
|  | @ -345,7 +320,7 @@ namespace Kav | |||
|                 directionalLight.Color.ToVector3() * directionalLight.Intensity; | ||||
|              | ||||
|             DeferredDirectionalLightEffect.ViewMatrix = camera.View; | ||||
|             DeferredDirectionalLightEffect.EyePosition = Matrix.Invert(camera.View).Translation; | ||||
|             DeferredDirectionalLightEffect.EyePosition = camera.Position; | ||||
| 
 | ||||
|             GraphicsDevice.SetRenderTarget(ColorRenderTarget); | ||||
|             GraphicsDevice.BlendState = BlendState.Additive; | ||||
|  | @ -360,11 +335,18 @@ namespace Kav | |||
| 
 | ||||
|         private void DirectionalLightToonRender( | ||||
|             PerspectiveCamera camera, | ||||
|             IEnumerable<(Model, Matrix)> modelTransforms, | ||||
|             DirectionalLight directionalLight | ||||
|         ) { | ||||
|             RenderShadows(camera, modelTransforms, directionalLight, Deferred_ToonEffect); | ||||
| 
 | ||||
|             GraphicsDevice.SetRenderTarget(ColorRenderTarget); | ||||
|             GraphicsDevice.BlendState = BlendState.Additive; | ||||
| 
 | ||||
|             Deferred_ToonEffect.GPosition = gPosition; | ||||
|             Deferred_ToonEffect.GAlbedo = gAlbedo; | ||||
|             Deferred_ToonEffect.GNormal = gNormal; | ||||
| 
 | ||||
|             Deferred_ToonEffect.EyePosition = camera.Position; | ||||
|             Deferred_ToonEffect.DirectionalLightDirection = directionalLight.Direction; | ||||
|             Deferred_ToonEffect.DirectionalLightColor =  | ||||
|  | @ -372,6 +354,22 @@ namespace Kav | |||
| 
 | ||||
|             Deferred_ToonEffect.Softness = 0.01f; | ||||
| 
 | ||||
|             Deferred_ToonEffect.ShadowMapOne = ShadowRenderTargets[0]; | ||||
|             if (NumShadowCascades > 1) | ||||
|             { | ||||
|                 Deferred_ToonEffect.ShadowMapTwo = ShadowRenderTargets[1]; | ||||
|             } | ||||
|             if (NumShadowCascades > 2) | ||||
|             { | ||||
|                 Deferred_ToonEffect.ShadowMapThree = ShadowRenderTargets[2]; | ||||
|             } | ||||
|             if (NumShadowCascades > 3) | ||||
|             { | ||||
|                 Deferred_ToonEffect.ShadowMapFour = ShadowRenderTargets[3]; | ||||
|             } | ||||
|              | ||||
|             Deferred_ToonEffect.ViewMatrix = camera.View; | ||||
| 
 | ||||
|             foreach (EffectPass pass in Deferred_ToonEffect.CurrentTechnique.Passes) | ||||
|             { | ||||
|                 pass.Apply(); | ||||
|  | @ -380,10 +378,42 @@ namespace Kav | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private void RenderShadows( | ||||
|             PerspectiveCamera camera, | ||||
|             IEnumerable<(Model, Matrix)> modelTransforms, | ||||
|             DirectionalLight directionalLight, | ||||
|             ShadowCascadeEffect effect | ||||
|         ) { | ||||
|             // render the individual shadow cascades | ||||
|             var previousFarPlane = camera.NearPlane; | ||||
|             for (var i = 0; i < NumShadowCascades; i++) | ||||
|             { | ||||
|                 var farPlane = camera.FarPlane / (MathHelper.Max((NumShadowCascades - i - 1) * 2f, 1f)); | ||||
| 
 | ||||
|                 // divide the view frustum  | ||||
|                 var shadowCamera = new PerspectiveCamera( | ||||
|                     camera.Position, | ||||
|                     camera.Forward, | ||||
|                     camera.Up, | ||||
|                     camera.FieldOfView, | ||||
|                     camera.AspectRatio, | ||||
|                     previousFarPlane, | ||||
|                     farPlane | ||||
|                 ); | ||||
|                  | ||||
|                 // TODO: This is tightly coupled to the effect and it sucks | ||||
|                 RenderShadowMap(shadowCamera, modelTransforms, directionalLight, effect, i); | ||||
| 
 | ||||
|                 effect.CascadeFarPlanes[i] = farPlane; | ||||
|                 previousFarPlane = farPlane; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private void RenderShadowMap( | ||||
|             PerspectiveCamera camera,  | ||||
|             IEnumerable<(Model, Matrix)> modelTransforms,  | ||||
|             DirectionalLight directionalLight, | ||||
|             ShadowCascadeEffect effect, | ||||
|             int shadowCascadeIndex | ||||
|         ) { | ||||
|             GraphicsDevice.SetRenderTarget(ShadowRenderTargets[shadowCascadeIndex]); | ||||
|  | @ -424,23 +454,21 @@ namespace Kav | |||
| 
 | ||||
|             if (shadowCascadeIndex == 0) | ||||
|             { | ||||
|                 DeferredDirectionalLightEffect.LightSpaceMatrixOne = lightSpaceMatrix; | ||||
|                 effect.LightSpaceMatrixOne = lightSpaceMatrix; | ||||
|             } | ||||
|             else if (shadowCascadeIndex == 1) | ||||
|             { | ||||
|                 DeferredDirectionalLightEffect.LightSpaceMatrixTwo = lightSpaceMatrix; | ||||
|                 effect.LightSpaceMatrixTwo = lightSpaceMatrix; | ||||
|             } | ||||
|             else if (shadowCascadeIndex == 2) | ||||
|             { | ||||
|                 DeferredDirectionalLightEffect.LightSpaceMatrixThree = lightSpaceMatrix; | ||||
|                 effect.LightSpaceMatrixThree = lightSpaceMatrix; | ||||
|             } | ||||
|             else if (shadowCascadeIndex == 3) | ||||
|             { | ||||
|                 DeferredDirectionalLightEffect.LightSpaceMatrixFour = lightSpaceMatrix; | ||||
|                 effect.LightSpaceMatrixFour = lightSpaceMatrix; | ||||
|             } | ||||
| 
 | ||||
|             DeferredDirectionalLightEffect.CascadeFarPlanes[shadowCascadeIndex] = camera.FarPlane; | ||||
| 
 | ||||
|             foreach (var (model, transform) in modelTransforms) | ||||
|             { | ||||
|                 foreach (var modelMesh in model.Meshes) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue