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,8 +1,15 @@
|
|||
#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
|
||||
|
||||
|
@ -13,6 +20,19 @@ float3 DirectionalLightColor _ps(c2) _cb(c2);
|
|||
|
||||
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
|
||||
|
||||
struct VertexInput
|
||||
|
@ -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