shadow refactor
parent
84601379b5
commit
96f6d22896
|
@ -0,0 +1,58 @@
|
|||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace Kav
|
||||
{
|
||||
public class DirectionalShadowMapData
|
||||
{
|
||||
public static readonly int MAX_SHADOW_CASCADES = 4;
|
||||
|
||||
public RenderTarget2D[] ShadowMaps { get; }
|
||||
|
||||
public Matrix LightSpaceMatrixOne { get; set; }
|
||||
public Matrix LightSpaceMatrixTwo { get; set; }
|
||||
public Matrix LightSpaceMatrixThree { get; set; }
|
||||
public Matrix LightSpaceMatrixFour { get; set; }
|
||||
|
||||
public float[] CascadeFarPlanes { get; }
|
||||
|
||||
public int ShadowMapSize { get; }
|
||||
public int NumShadowCascades { get; }
|
||||
|
||||
internal DirectionalShadowMapData(
|
||||
GraphicsDevice graphicsDevice,
|
||||
int shadowMapSize,
|
||||
int numCascades
|
||||
) {
|
||||
ShadowMapSize = shadowMapSize;
|
||||
NumShadowCascades = (int)MathHelper.Clamp(numCascades, 1, MAX_SHADOW_CASCADES);
|
||||
|
||||
ShadowMaps = new RenderTarget2D[NumShadowCascades];
|
||||
|
||||
for (var i = 0; i < NumShadowCascades; i++)
|
||||
{
|
||||
ShadowMaps[i] = new RenderTarget2D(
|
||||
graphicsDevice,
|
||||
shadowMapSize,
|
||||
shadowMapSize,
|
||||
false,
|
||||
SurfaceFormat.Single,
|
||||
DepthFormat.Depth24,
|
||||
0,
|
||||
RenderTargetUsage.PreserveContents
|
||||
);
|
||||
}
|
||||
|
||||
CascadeFarPlanes = new float[MAX_SHADOW_CASCADES];
|
||||
}
|
||||
|
||||
public void Clear(GraphicsDevice graphicsDevice)
|
||||
{
|
||||
foreach (var shadowMap in ShadowMaps)
|
||||
{
|
||||
graphicsDevice.SetRenderTarget(shadowMap);
|
||||
graphicsDevice.Clear(Color.White);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
215
Renderer.cs
215
Renderer.cs
|
@ -10,15 +10,10 @@ namespace Kav
|
|||
{
|
||||
private const int MAX_INSTANCE_VERTEX_COUNT = 1000000;
|
||||
private const int MAX_SHADOW_CASCADES = 4;
|
||||
private int ShadowMapSize { get; }
|
||||
|
||||
private GraphicsDevice GraphicsDevice { get; }
|
||||
|
||||
private VertexBuffer FullscreenTriangle { get; }
|
||||
private int NumShadowCascades { get; }
|
||||
|
||||
private RenderTarget2D ColorRenderTarget { get; }
|
||||
private RenderTarget2D[] ShadowRenderTargets { get; }
|
||||
|
||||
private DeferredPBREffect DeferredPBREffect { get; }
|
||||
/* FIXME: these next two dont actually have anything to do with PBR */
|
||||
|
@ -33,8 +28,6 @@ namespace Kav
|
|||
private SkyboxEffect SkyboxEffect { get; }
|
||||
private DiffuseLitSpriteEffect DiffuseLitSpriteEffect { get; }
|
||||
|
||||
private RenderTargetCube PointShadowCubeMap { get; }
|
||||
|
||||
private Kav.Model UnitCube { get; }
|
||||
|
||||
private SpriteBatch SpriteBatch { get; }
|
||||
|
@ -43,50 +36,10 @@ namespace Kav
|
|||
private readonly GBufferInstanceVertex[] GBufferInstanceVertices = new GBufferInstanceVertex[MAX_INSTANCE_VERTEX_COUNT];
|
||||
|
||||
public Renderer(
|
||||
GraphicsDevice graphicsDevice,
|
||||
int renderDimensionsX,
|
||||
int renderDimensionsY,
|
||||
int numShadowCascades,
|
||||
int shadowMapSize
|
||||
GraphicsDevice graphicsDevice
|
||||
) {
|
||||
GraphicsDevice = graphicsDevice;
|
||||
|
||||
ShadowMapSize = shadowMapSize;
|
||||
|
||||
NumShadowCascades = (int)MathHelper.Clamp(numShadowCascades, 1, MAX_SHADOW_CASCADES);
|
||||
ShadowRenderTargets = new RenderTarget2D[numShadowCascades];
|
||||
|
||||
for (var i = 0; i < numShadowCascades; i++)
|
||||
{
|
||||
ShadowRenderTargets[i] = new RenderTarget2D(
|
||||
GraphicsDevice,
|
||||
ShadowMapSize,
|
||||
ShadowMapSize,
|
||||
false,
|
||||
SurfaceFormat.Single,
|
||||
DepthFormat.Depth24
|
||||
);
|
||||
}
|
||||
|
||||
ColorRenderTarget = new RenderTarget2D(
|
||||
graphicsDevice,
|
||||
renderDimensionsX,
|
||||
renderDimensionsY,
|
||||
false,
|
||||
SurfaceFormat.Color,
|
||||
DepthFormat.Depth24,
|
||||
0,
|
||||
RenderTargetUsage.PreserveContents
|
||||
);
|
||||
|
||||
PointShadowCubeMap = new RenderTargetCube(
|
||||
GraphicsDevice,
|
||||
shadowMapSize,
|
||||
false,
|
||||
SurfaceFormat.Single,
|
||||
DepthFormat.Depth24
|
||||
);
|
||||
|
||||
SimpleDepthEffect = new SimpleDepthEffect(GraphicsDevice);
|
||||
LinearDepthEffect = new LinearDepthEffect(GraphicsDevice);
|
||||
DeferredPBREffect = new DeferredPBREffect(GraphicsDevice);
|
||||
|
@ -95,7 +48,6 @@ namespace Kav
|
|||
DeferredAmbientLightEffect = new DeferredPBR_AmbientLightEffect(GraphicsDevice);
|
||||
DeferredPointLightEffect = new DeferredPBR_PointLightEffect(GraphicsDevice);
|
||||
DeferredDirectionalLightEffect = new DeferredPBR_DirectionalLightEffect(GraphicsDevice);
|
||||
DeferredDirectionalLightEffect.ShadowMapSize = ShadowMapSize;
|
||||
ToneMapEffect = new Effect(graphicsDevice, Resources.ToneMapEffect);
|
||||
Deferred_ToonEffect = new Deferred_ToonEffect(GraphicsDevice);
|
||||
SkyboxEffect = new SkyboxEffect(GraphicsDevice);
|
||||
|
@ -123,6 +75,33 @@ namespace Kav
|
|||
);
|
||||
}
|
||||
|
||||
public static RenderTargetCube CreateShadowCubeMap(
|
||||
GraphicsDevice graphicsDevice,
|
||||
int shadowMapSize
|
||||
) {
|
||||
return new RenderTargetCube(
|
||||
graphicsDevice,
|
||||
shadowMapSize,
|
||||
false,
|
||||
SurfaceFormat.Single,
|
||||
DepthFormat.Depth24,
|
||||
0,
|
||||
RenderTargetUsage.PreserveContents
|
||||
);
|
||||
}
|
||||
|
||||
public static DirectionalShadowMapData CreateDirectionalShadowMaps(
|
||||
GraphicsDevice graphicsDevice,
|
||||
int shadowMapSize,
|
||||
int numCascades
|
||||
) {
|
||||
return new DirectionalShadowMapData(
|
||||
graphicsDevice,
|
||||
shadowMapSize,
|
||||
numCascades
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: we could make this a lot more efficient probably
|
||||
// draws mesh sprites with a forward rendered diffuse lighting technique
|
||||
public void MeshSpriteRender(
|
||||
|
@ -338,7 +317,7 @@ namespace Kav
|
|||
}
|
||||
}
|
||||
|
||||
public void RenderDepth<T>(
|
||||
public void RenderDepthIndexed<T>(
|
||||
RenderTarget2D renderTarget,
|
||||
PerspectiveCamera camera,
|
||||
IEnumerable<(T, Matrix)> drawableTransforms
|
||||
|
@ -488,18 +467,16 @@ namespace Kav
|
|||
RenderFullscreenEffect(DeferredAmbientLightEffect);
|
||||
}
|
||||
|
||||
public void RenderPointLight<T>(
|
||||
public void RenderPointLight(
|
||||
RenderTarget2D renderTarget,
|
||||
Texture2D gPosition,
|
||||
Texture2D gAlbedo,
|
||||
Texture2D gNormal,
|
||||
Texture2D gMetallicRoughness,
|
||||
TextureCube shadowMap,
|
||||
PerspectiveCamera camera,
|
||||
IEnumerable<(T, Matrix)> modelTransforms,
|
||||
PointLight pointLight
|
||||
) where T : ICullable, IIndexDrawable {
|
||||
RenderPointShadows(PointShadowCubeMap, camera, modelTransforms, pointLight);
|
||||
|
||||
) {
|
||||
GraphicsDevice.SetRenderTarget(renderTarget);
|
||||
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
||||
GraphicsDevice.BlendState = BlendState.Additive;
|
||||
|
@ -508,7 +485,7 @@ namespace Kav
|
|||
DeferredPointLightEffect.GAlbedo = gAlbedo;
|
||||
DeferredPointLightEffect.GNormal = gNormal;
|
||||
DeferredPointLightEffect.GMetallicRoughness = gMetallicRoughness;
|
||||
DeferredPointLightEffect.ShadowMap = PointShadowCubeMap;
|
||||
DeferredPointLightEffect.ShadowMap = shadowMap;
|
||||
|
||||
DeferredPointLightEffect.EyePosition = camera.Position;
|
||||
|
||||
|
@ -530,10 +507,8 @@ namespace Kav
|
|||
PerspectiveCamera camera,
|
||||
IEnumerable<(T, Matrix)> modelTransforms,
|
||||
DirectionalLight directionalLight,
|
||||
int numShadowCascades
|
||||
DirectionalShadowMapData shadowMapData
|
||||
) where T : ICullable, IIndexDrawable {
|
||||
//RenderDirectionalShadows(camera, modelTransforms, directionalLight, DeferredDirectionalLightEffect);
|
||||
|
||||
GraphicsDevice.SetRenderTarget(renderTarget);
|
||||
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
||||
GraphicsDevice.BlendState = BlendState.Additive;
|
||||
|
@ -543,18 +518,25 @@ namespace Kav
|
|||
DeferredDirectionalLightEffect.GNormal = gNormal;
|
||||
DeferredDirectionalLightEffect.GMetallicRoughness = gMetallicRoughness;
|
||||
|
||||
DeferredDirectionalLightEffect.ShadowMapOne = ShadowRenderTargets[0];
|
||||
if (numShadowCascades > 1)
|
||||
DeferredDirectionalLightEffect.ShadowMapSize = shadowMapData.ShadowMapSize;
|
||||
|
||||
DeferredDirectionalLightEffect.ShadowMapOne = shadowMapData.ShadowMaps[0];
|
||||
DeferredDirectionalLightEffect.LightSpaceMatrixOne = shadowMapData.LightSpaceMatrixOne;
|
||||
|
||||
if (shadowMapData.NumShadowCascades > 1)
|
||||
{
|
||||
DeferredDirectionalLightEffect.ShadowMapTwo = ShadowRenderTargets[1];
|
||||
DeferredDirectionalLightEffect.ShadowMapTwo = shadowMapData.ShadowMaps[1];
|
||||
DeferredDirectionalLightEffect.LightSpaceMatrixTwo = shadowMapData.LightSpaceMatrixTwo;
|
||||
}
|
||||
if (numShadowCascades > 2)
|
||||
if (shadowMapData.NumShadowCascades > 2)
|
||||
{
|
||||
DeferredDirectionalLightEffect.ShadowMapThree = ShadowRenderTargets[2];
|
||||
DeferredDirectionalLightEffect.ShadowMapThree = shadowMapData.ShadowMaps[2];
|
||||
DeferredDirectionalLightEffect.LightSpaceMatrixThree = shadowMapData.LightSpaceMatrixThree;
|
||||
}
|
||||
if (numShadowCascades > 3)
|
||||
if (shadowMapData.NumShadowCascades > 3)
|
||||
{
|
||||
DeferredDirectionalLightEffect.ShadowMapFour = ShadowRenderTargets[3];
|
||||
DeferredDirectionalLightEffect.ShadowMapFour = shadowMapData.ShadowMaps[3];
|
||||
DeferredDirectionalLightEffect.LightSpaceMatrixFour = shadowMapData.LightSpaceMatrixFour;
|
||||
}
|
||||
|
||||
DeferredDirectionalLightEffect.DirectionalLightDirection = directionalLight.Direction;
|
||||
|
@ -573,14 +555,12 @@ namespace Kav
|
|||
Texture2D gAlbedo,
|
||||
Texture2D gNormal,
|
||||
Texture2D gMetallicRoughness,
|
||||
DirectionalShadowMapData shadowMapData,
|
||||
PerspectiveCamera camera,
|
||||
IEnumerable<(T, Matrix)> modelTransforms,
|
||||
DirectionalLight directionalLight,
|
||||
int numShadowCascades,
|
||||
bool ditheredShadows
|
||||
) where T : ICullable, IIndexDrawable {
|
||||
//RenderDirectionalShadows(camera, modelTransforms, directionalLight, Deferred_ToonEffect);
|
||||
|
||||
GraphicsDevice.SetRenderTarget(renderTarget);
|
||||
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
||||
GraphicsDevice.BlendState = BlendState.Additive;
|
||||
|
@ -598,18 +578,23 @@ namespace Kav
|
|||
Deferred_ToonEffect.DirectionalLightColor =
|
||||
directionalLight.Color.ToVector3() * directionalLight.Intensity;
|
||||
|
||||
Deferred_ToonEffect.ShadowMapOne = ShadowRenderTargets[0];
|
||||
if (numShadowCascades > 1)
|
||||
Deferred_ToonEffect.ShadowMapOne = shadowMapData.ShadowMaps[0];
|
||||
Deferred_ToonEffect.LightSpaceMatrixOne = shadowMapData.LightSpaceMatrixOne;
|
||||
|
||||
if (shadowMapData.NumShadowCascades > 1)
|
||||
{
|
||||
Deferred_ToonEffect.ShadowMapTwo = ShadowRenderTargets[1];
|
||||
Deferred_ToonEffect.ShadowMapTwo = shadowMapData.ShadowMaps[1];
|
||||
Deferred_ToonEffect.LightSpaceMatrixTwo = shadowMapData.LightSpaceMatrixTwo;
|
||||
}
|
||||
if (numShadowCascades > 2)
|
||||
if (shadowMapData.NumShadowCascades > 2)
|
||||
{
|
||||
Deferred_ToonEffect.ShadowMapThree = ShadowRenderTargets[2];
|
||||
Deferred_ToonEffect.ShadowMapThree = shadowMapData.ShadowMaps[2];
|
||||
Deferred_ToonEffect.LightSpaceMatrixThree = shadowMapData.LightSpaceMatrixThree;
|
||||
}
|
||||
if (numShadowCascades > 3)
|
||||
if (shadowMapData.NumShadowCascades > 3)
|
||||
{
|
||||
Deferred_ToonEffect.ShadowMapFour = ShadowRenderTargets[3];
|
||||
Deferred_ToonEffect.ShadowMapFour = shadowMapData.ShadowMaps[3];
|
||||
Deferred_ToonEffect.LightSpaceMatrixFour = shadowMapData.LightSpaceMatrixFour;
|
||||
}
|
||||
|
||||
Deferred_ToonEffect.ViewMatrix = camera.View;
|
||||
|
@ -617,17 +602,17 @@ namespace Kav
|
|||
RenderFullscreenEffect(Deferred_ToonEffect);
|
||||
}
|
||||
|
||||
private void RenderDirectionalShadows<T>(
|
||||
public void RenderDirectionalShadowsIndexed<T>(
|
||||
DirectionalShadowMapData shadowMapData,
|
||||
PerspectiveCamera camera,
|
||||
IEnumerable<(Model, Matrix)> modelTransforms,
|
||||
DirectionalLight directionalLight,
|
||||
ShadowCascadeEffect effect
|
||||
IEnumerable<(T, Matrix)> drawableTransforms,
|
||||
DirectionalLight directionalLight
|
||||
) where T : ICullable, IIndexDrawable {
|
||||
// render the individual shadow cascades
|
||||
var previousFarPlane = camera.NearPlane;
|
||||
for (var i = 0; i < NumShadowCascades; i++)
|
||||
for (var i = 0; i < shadowMapData.NumShadowCascades; i++)
|
||||
{
|
||||
var farPlane = camera.FarPlane / (MathHelper.Max((NumShadowCascades - i - 1) * 2f, 1f));
|
||||
var farPlane = camera.FarPlane / (MathHelper.Max((shadowMapData.NumShadowCascades - i - 1) * 2f, 1f));
|
||||
|
||||
// divide the view frustum
|
||||
var shadowCamera = new PerspectiveCamera(
|
||||
|
@ -640,23 +625,27 @@ namespace Kav
|
|||
farPlane
|
||||
);
|
||||
|
||||
// TODO: This is tightly coupled to the effect and it sucks
|
||||
RenderDirectionalShadowMap(shadowCamera, modelTransforms, directionalLight, effect, i);
|
||||
RenderDirectionalShadowMapIndexed(
|
||||
shadowMapData,
|
||||
i,
|
||||
shadowCamera,
|
||||
drawableTransforms,
|
||||
directionalLight
|
||||
);
|
||||
|
||||
effect.CascadeFarPlanes[i] = farPlane;
|
||||
shadowMapData.CascadeFarPlanes[i] = farPlane;
|
||||
previousFarPlane = farPlane;
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderDirectionalShadowMap(
|
||||
public void RenderDirectionalShadowMapIndexed<T>(
|
||||
DirectionalShadowMapData shadowMapData,
|
||||
int shadowCascadeIndex,
|
||||
PerspectiveCamera camera,
|
||||
IEnumerable<(Model, Matrix)> modelTransforms,
|
||||
DirectionalLight directionalLight,
|
||||
ShadowCascadeEffect effect,
|
||||
int shadowCascadeIndex
|
||||
) {
|
||||
GraphicsDevice.SetRenderTarget(ShadowRenderTargets[shadowCascadeIndex]);
|
||||
GraphicsDevice.Clear(Color.White);
|
||||
IEnumerable<(T, Matrix)> drawableTransforms,
|
||||
DirectionalLight directionalLight
|
||||
) where T : ICullable, IIndexDrawable {
|
||||
GraphicsDevice.SetRenderTarget(shadowMapData.ShadowMaps[shadowCascadeIndex]);
|
||||
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
||||
GraphicsDevice.BlendState = BlendState.Opaque;
|
||||
|
||||
|
@ -693,53 +682,25 @@ namespace Kav
|
|||
|
||||
if (shadowCascadeIndex == 0)
|
||||
{
|
||||
effect.LightSpaceMatrixOne = lightSpaceMatrix;
|
||||
shadowMapData.LightSpaceMatrixOne = lightSpaceMatrix;
|
||||
}
|
||||
else if (shadowCascadeIndex == 1)
|
||||
{
|
||||
effect.LightSpaceMatrixTwo = lightSpaceMatrix;
|
||||
shadowMapData.LightSpaceMatrixTwo = lightSpaceMatrix;
|
||||
}
|
||||
else if (shadowCascadeIndex == 2)
|
||||
{
|
||||
effect.LightSpaceMatrixThree = lightSpaceMatrix;
|
||||
shadowMapData.LightSpaceMatrixThree = lightSpaceMatrix;
|
||||
}
|
||||
else if (shadowCascadeIndex == 3)
|
||||
{
|
||||
effect.LightSpaceMatrixFour = lightSpaceMatrix;
|
||||
shadowMapData.LightSpaceMatrixFour = lightSpaceMatrix;
|
||||
}
|
||||
|
||||
var boundingFrustum = new BoundingFrustum(lightSpaceMatrix);
|
||||
|
||||
foreach (var (model, transform) in FrustumCull(boundingFrustum, modelTransforms))
|
||||
{
|
||||
foreach (var modelMesh in model.Meshes)
|
||||
{
|
||||
foreach (var meshPart in modelMesh.MeshParts)
|
||||
{
|
||||
GraphicsDevice.SetVertexBuffer(meshPart.VertexBuffer);
|
||||
GraphicsDevice.Indices = meshPart.IndexBuffer;
|
||||
|
||||
SimpleDepthEffect.World = transform;
|
||||
|
||||
foreach (var pass in SimpleDepthEffect.CurrentTechnique.Passes)
|
||||
{
|
||||
pass.Apply();
|
||||
|
||||
GraphicsDevice.DrawIndexedPrimitives(
|
||||
PrimitiveType.TriangleList,
|
||||
0,
|
||||
0,
|
||||
meshPart.VertexBuffer.VertexCount,
|
||||
0,
|
||||
meshPart.Triangles.Length
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
CullAndRenderIndexed(GraphicsDevice, camera, drawableTransforms, SimpleDepthEffect);
|
||||
}
|
||||
|
||||
private void RenderPointShadows<T>(
|
||||
public void RenderPointShadowsIndexed<T>(
|
||||
RenderTargetCube pointShadowCubeMap,
|
||||
PerspectiveCamera camera,
|
||||
IEnumerable<(T, Matrix)> modelTransforms,
|
||||
|
|
Loading…
Reference in New Issue