started adding support for instanced draws + started decoupling API
parent
c9a4e35816
commit
ee8b0c5ee8
|
@ -17,6 +17,7 @@ namespace Kav
|
||||||
EffectParameter metallicParam;
|
EffectParameter metallicParam;
|
||||||
EffectParameter roughnessParam;
|
EffectParameter roughnessParam;
|
||||||
|
|
||||||
|
EffectParameter vertexShaderIndexParam;
|
||||||
EffectParameter shaderIndexParam;
|
EffectParameter shaderIndexParam;
|
||||||
|
|
||||||
Matrix world = Matrix.Identity;
|
Matrix world = Matrix.Identity;
|
||||||
|
@ -30,6 +31,7 @@ namespace Kav
|
||||||
bool albedoTextureEnabled = false;
|
bool albedoTextureEnabled = false;
|
||||||
bool metallicRoughnessMapEnabled = false;
|
bool metallicRoughnessMapEnabled = false;
|
||||||
bool normalMapEnabled = false;
|
bool normalMapEnabled = false;
|
||||||
|
bool hardwareInstancingEnabled = false;
|
||||||
|
|
||||||
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
|
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
|
||||||
|
|
||||||
|
@ -100,7 +102,7 @@ namespace Kav
|
||||||
{
|
{
|
||||||
albedoTextureParam.SetValue(value);
|
albedoTextureParam.SetValue(value);
|
||||||
albedoTextureEnabled = value != null;
|
albedoTextureEnabled = value != null;
|
||||||
dirtyFlags |= EffectDirtyFlags.ShaderIndex;
|
dirtyFlags |= EffectDirtyFlags.PixelShaderIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +113,7 @@ namespace Kav
|
||||||
{
|
{
|
||||||
normalTextureParam.SetValue(value);
|
normalTextureParam.SetValue(value);
|
||||||
normalMapEnabled = value != null;
|
normalMapEnabled = value != null;
|
||||||
dirtyFlags |= EffectDirtyFlags.ShaderIndex;
|
dirtyFlags |= EffectDirtyFlags.PixelShaderIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +124,20 @@ namespace Kav
|
||||||
{
|
{
|
||||||
metallicRoughnessTextureParam.SetValue(value);
|
metallicRoughnessTextureParam.SetValue(value);
|
||||||
metallicRoughnessMapEnabled = value != null;
|
metallicRoughnessMapEnabled = value != null;
|
||||||
dirtyFlags |= EffectDirtyFlags.ShaderIndex;
|
dirtyFlags |= EffectDirtyFlags.PixelShaderIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HardwareInstancingEnabled
|
||||||
|
{
|
||||||
|
get { return hardwareInstancingEnabled; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != hardwareInstancingEnabled)
|
||||||
|
{
|
||||||
|
hardwareInstancingEnabled = value;
|
||||||
|
dirtyFlags |= EffectDirtyFlags.VertexShaderIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,14 +190,19 @@ namespace Kav
|
||||||
dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
|
dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dirtyFlags & EffectDirtyFlags.EyePosition) != 0)
|
if ((dirtyFlags & EffectDirtyFlags.VertexShaderIndex) != 0)
|
||||||
{
|
{
|
||||||
Matrix.Invert(ref view, out Matrix inverseView);
|
int vertexShaderIndex = 0;
|
||||||
|
|
||||||
dirtyFlags &= ~EffectDirtyFlags.EyePosition;
|
if (hardwareInstancingEnabled)
|
||||||
|
{
|
||||||
|
vertexShaderIndex = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertexShaderIndexParam.SetValue(vertexShaderIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dirtyFlags & EffectDirtyFlags.ShaderIndex) != 0)
|
if ((dirtyFlags & EffectDirtyFlags.PixelShaderIndex) != 0)
|
||||||
{
|
{
|
||||||
int shaderIndex = 0;
|
int shaderIndex = 0;
|
||||||
|
|
||||||
|
@ -217,7 +237,7 @@ namespace Kav
|
||||||
|
|
||||||
shaderIndexParam.SetValue(shaderIndex);
|
shaderIndexParam.SetValue(shaderIndex);
|
||||||
|
|
||||||
dirtyFlags &= ~EffectDirtyFlags.ShaderIndex;
|
dirtyFlags &= ~EffectDirtyFlags.PixelShaderIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +255,8 @@ namespace Kav
|
||||||
metallicParam = Parameters["MetallicValue"];
|
metallicParam = Parameters["MetallicValue"];
|
||||||
roughnessParam = Parameters["RoughnessValue"];
|
roughnessParam = Parameters["RoughnessValue"];
|
||||||
|
|
||||||
shaderIndexParam = Parameters["ShaderIndex"];
|
shaderIndexParam = Parameters["PixelShaderIndex"];
|
||||||
|
vertexShaderIndexParam = Parameters["VertexShaderIndex"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace Kav
|
||||||
if (normalMapEnabled != value)
|
if (normalMapEnabled != value)
|
||||||
{
|
{
|
||||||
normalMapEnabled = value;
|
normalMapEnabled = value;
|
||||||
dirtyFlags |= EffectDirtyFlags.ShaderIndex;
|
dirtyFlags |= EffectDirtyFlags.PixelShaderIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@ namespace Kav
|
||||||
dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
|
dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dirtyFlags & EffectDirtyFlags.ShaderIndex) != 0)
|
if ((dirtyFlags & EffectDirtyFlags.PixelShaderIndex) != 0)
|
||||||
{
|
{
|
||||||
int shaderIndex = 0;
|
int shaderIndex = 0;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,8 @@ namespace Kav
|
||||||
WorldViewProj = 1,
|
WorldViewProj = 1,
|
||||||
World = 2,
|
World = 2,
|
||||||
EyePosition = 4,
|
EyePosition = 4,
|
||||||
ShaderIndex = 8,
|
VertexShaderIndex = 8,
|
||||||
|
PixelShaderIndex = 16,
|
||||||
All = -1
|
All = -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
BIN
Effects/FXB/DeferredPBR_GBufferEffect.fxb (Stored with Git LFS)
BIN
Effects/FXB/DeferredPBR_GBufferEffect.fxb (Stored with Git LFS)
Binary file not shown.
|
@ -25,6 +25,13 @@ struct VertexInput
|
||||||
float2 TexCoord : TEXCOORD0;
|
float2 TexCoord : TEXCOORD0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct InstanceInput
|
||||||
|
{
|
||||||
|
float4x4 World : TEXCOORD0;
|
||||||
|
float4x4 WorldInverseTranspose : TEXCOORD1;
|
||||||
|
float4x4 WorldViewProjection : TEXCOORD2;
|
||||||
|
};
|
||||||
|
|
||||||
struct PixelInput
|
struct PixelInput
|
||||||
{
|
{
|
||||||
float4 Position : SV_POSITION;
|
float4 Position : SV_POSITION;
|
||||||
|
@ -55,6 +62,18 @@ PixelInput main_vs(VertexInput input)
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PixelInput instanced_vs(VertexInput input, InstanceInput instanceInput)
|
||||||
|
{
|
||||||
|
PixelInput output;
|
||||||
|
|
||||||
|
output.PositionWorld = mul(input.Position, instanceInput.World).xyz;
|
||||||
|
output.NormalWorld = mul(input.Normal, (float3x3)instanceInput.WorldInverseTranspose).xyz;
|
||||||
|
output.TexCoord = input.TexCoord;
|
||||||
|
output.Position = mul(input.Position, instanceInput.WorldViewProjection);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
// Pixel Shaders
|
// Pixel Shaders
|
||||||
|
|
||||||
// Easy trick to get tangent-normals to world-space to keep PBR code simplified.
|
// Easy trick to get tangent-normals to world-space to keep PBR code simplified.
|
||||||
|
@ -171,6 +190,19 @@ PixelOutput AlbedoMetallicRoughnessNormalMapPS(PixelInput input)
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VertexShader VSArray[2] =
|
||||||
|
{
|
||||||
|
compile vs_3_0 main_vs(),
|
||||||
|
compile vs_3_0 instanced_vs()
|
||||||
|
};
|
||||||
|
|
||||||
|
int VSIndices[2] =
|
||||||
|
{
|
||||||
|
0, 1
|
||||||
|
};
|
||||||
|
|
||||||
|
int VertexShaderIndex = 0;
|
||||||
|
|
||||||
PixelShader PSArray[8] =
|
PixelShader PSArray[8] =
|
||||||
{
|
{
|
||||||
compile ps_3_0 NonePS(),
|
compile ps_3_0 NonePS(),
|
||||||
|
@ -191,13 +223,13 @@ int PSIndices[8] =
|
||||||
0, 1, 2, 3, 4, 5, 6, 7
|
0, 1, 2, 3, 4, 5, 6, 7
|
||||||
};
|
};
|
||||||
|
|
||||||
int ShaderIndex = 0;
|
int PixelShaderIndex = 0;
|
||||||
|
|
||||||
Technique GBuffer
|
Technique GBuffer
|
||||||
{
|
{
|
||||||
Pass
|
Pass
|
||||||
{
|
{
|
||||||
VertexShader = compile vs_3_0 main_vs();
|
VertexShader = (VSArray[VSIndices[VertexShaderIndex]]);
|
||||||
PixelShader = (PSArray[PSIndices[ShaderIndex]]);
|
PixelShader = (PSArray[PSIndices[PixelShaderIndex]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,7 @@ namespace Kav
|
||||||
{
|
{
|
||||||
albedoTextureParam.SetValue(value);
|
albedoTextureParam.SetValue(value);
|
||||||
albedoTextureEnabled = value != null;
|
albedoTextureEnabled = value != null;
|
||||||
dirtyFlags |= EffectDirtyFlags.ShaderIndex;
|
dirtyFlags |= EffectDirtyFlags.PixelShaderIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ namespace Kav
|
||||||
{
|
{
|
||||||
normalTextureParam.SetValue(value);
|
normalTextureParam.SetValue(value);
|
||||||
normalMapEnabled = value != null;
|
normalMapEnabled = value != null;
|
||||||
dirtyFlags |= EffectDirtyFlags.ShaderIndex;
|
dirtyFlags |= EffectDirtyFlags.PixelShaderIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ namespace Kav
|
||||||
{
|
{
|
||||||
metallicRoughnessTextureParam.SetValue(value);
|
metallicRoughnessTextureParam.SetValue(value);
|
||||||
metallicRoughnessMapEnabled = value != null;
|
metallicRoughnessMapEnabled = value != null;
|
||||||
dirtyFlags |= EffectDirtyFlags.ShaderIndex;
|
dirtyFlags |= EffectDirtyFlags.PixelShaderIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,7 +266,7 @@ namespace Kav
|
||||||
dirtyFlags &= ~EffectDirtyFlags.EyePosition;
|
dirtyFlags &= ~EffectDirtyFlags.EyePosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dirtyFlags & EffectDirtyFlags.ShaderIndex) != 0)
|
if ((dirtyFlags & EffectDirtyFlags.PixelShaderIndex) != 0)
|
||||||
{
|
{
|
||||||
int shaderIndex = 0;
|
int shaderIndex = 0;
|
||||||
|
|
||||||
|
@ -301,7 +301,7 @@ namespace Kav
|
||||||
|
|
||||||
shaderIndexParam.SetValue(shaderIndex);
|
shaderIndexParam.SetValue(shaderIndex);
|
||||||
|
|
||||||
dirtyFlags &= ~EffectDirtyFlags.ShaderIndex;
|
dirtyFlags &= ~EffectDirtyFlags.PixelShaderIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Kav
|
||||||
|
{
|
||||||
|
public interface IGBufferDrawable
|
||||||
|
{
|
||||||
|
Vector3 Albedo { get; }
|
||||||
|
float Metallic { get; }
|
||||||
|
float Roughness { get; }
|
||||||
|
|
||||||
|
Texture2D AlbedoTexture { get; }
|
||||||
|
Texture2D NormalTexture { get; }
|
||||||
|
Texture2D MetallicRoughnessTexture { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Kav
|
||||||
|
{
|
||||||
|
public interface IIndexDrawable
|
||||||
|
{
|
||||||
|
VertexBuffer VertexBuffer { get; }
|
||||||
|
IndexBuffer IndexBuffer { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
namespace Kav
|
namespace Kav
|
||||||
{
|
{
|
||||||
public class MeshPart
|
public class MeshPart : IIndexDrawable
|
||||||
{
|
{
|
||||||
public IndexBuffer IndexBuffer { get; }
|
public IndexBuffer IndexBuffer { get; }
|
||||||
public VertexBuffer VertexBuffer { get; }
|
public VertexBuffer VertexBuffer { get; }
|
||||||
|
|
|
@ -4,7 +4,7 @@ using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
namespace Kav
|
namespace Kav
|
||||||
{
|
{
|
||||||
public class MeshSprite : ICullable
|
public class MeshSprite : ICullable, IIndexDrawable
|
||||||
{
|
{
|
||||||
private static readonly int PixelScale = 40;
|
private static readonly int PixelScale = 40;
|
||||||
private static readonly short[] Indices = new short[]
|
private static readonly short[] Indices = new short[]
|
||||||
|
|
244
Renderer.cs
244
Renderer.cs
|
@ -8,18 +8,16 @@ namespace Kav
|
||||||
{
|
{
|
||||||
public class Renderer
|
public class Renderer
|
||||||
{
|
{
|
||||||
|
private const int MAX_INSTANCE_VERTEX_COUNT = 1000000;
|
||||||
private const int MAX_SHADOW_CASCADES = 4;
|
private const int MAX_SHADOW_CASCADES = 4;
|
||||||
private int ShadowMapSize { get; }
|
private int ShadowMapSize { get; }
|
||||||
|
|
||||||
private GraphicsDevice GraphicsDevice { get; }
|
private GraphicsDevice GraphicsDevice { get; }
|
||||||
private int RenderDimensionsX { get; }
|
|
||||||
private int RenderDimensionsY { get; }
|
|
||||||
|
|
||||||
private VertexBuffer FullscreenTriangle { get; }
|
private VertexBuffer FullscreenTriangle { get; }
|
||||||
private int NumShadowCascades { get; }
|
private int NumShadowCascades { get; }
|
||||||
|
|
||||||
private RenderTarget2D ColorRenderTarget { get; }
|
private RenderTarget2D ColorRenderTarget { get; }
|
||||||
private RenderTarget2D DirectionalRenderTarget { get; }
|
|
||||||
private RenderTarget2D[] ShadowRenderTargets { get; }
|
private RenderTarget2D[] ShadowRenderTargets { get; }
|
||||||
|
|
||||||
private DeferredPBREffect DeferredPBREffect { get; }
|
private DeferredPBREffect DeferredPBREffect { get; }
|
||||||
|
@ -35,10 +33,10 @@ namespace Kav
|
||||||
private SkyboxEffect SkyboxEffect { get; }
|
private SkyboxEffect SkyboxEffect { get; }
|
||||||
private DiffuseLitSpriteEffect DiffuseLitSpriteEffect { get; }
|
private DiffuseLitSpriteEffect DiffuseLitSpriteEffect { get; }
|
||||||
|
|
||||||
private RenderTarget2D gPosition { get; }
|
private RenderTarget2D GPosition { get; }
|
||||||
private RenderTarget2D gNormal { get; }
|
private RenderTarget2D GNormal { get; }
|
||||||
private RenderTarget2D gAlbedo { get; }
|
private RenderTarget2D GAlbedo { get; }
|
||||||
private RenderTarget2D gMetallicRoughness { get; }
|
private RenderTarget2D GMetallicRoughness { get; }
|
||||||
private RenderTargetCube PointShadowCubeMap { get; }
|
private RenderTargetCube PointShadowCubeMap { get; }
|
||||||
|
|
||||||
private RenderTargetBinding[] GBuffer { get; }
|
private RenderTargetBinding[] GBuffer { get; }
|
||||||
|
@ -47,6 +45,9 @@ namespace Kav
|
||||||
|
|
||||||
private SpriteBatch SpriteBatch { get; }
|
private SpriteBatch SpriteBatch { get; }
|
||||||
|
|
||||||
|
private DynamicVertexBuffer GBufferInstanceVertexBuffer { get; }
|
||||||
|
private readonly GBufferInstanceVertex[] GBufferInstanceVertices = new GBufferInstanceVertex[MAX_INSTANCE_VERTEX_COUNT];
|
||||||
|
|
||||||
public Renderer(
|
public Renderer(
|
||||||
GraphicsDevice graphicsDevice,
|
GraphicsDevice graphicsDevice,
|
||||||
int renderDimensionsX,
|
int renderDimensionsX,
|
||||||
|
@ -55,8 +56,6 @@ namespace Kav
|
||||||
int shadowMapSize
|
int shadowMapSize
|
||||||
) {
|
) {
|
||||||
GraphicsDevice = graphicsDevice;
|
GraphicsDevice = graphicsDevice;
|
||||||
RenderDimensionsX = renderDimensionsX;
|
|
||||||
RenderDimensionsY = renderDimensionsY;
|
|
||||||
|
|
||||||
ShadowMapSize = shadowMapSize;
|
ShadowMapSize = shadowMapSize;
|
||||||
|
|
||||||
|
@ -86,18 +85,7 @@ namespace Kav
|
||||||
RenderTargetUsage.PreserveContents
|
RenderTargetUsage.PreserveContents
|
||||||
);
|
);
|
||||||
|
|
||||||
DirectionalRenderTarget = new RenderTarget2D(
|
GPosition = new RenderTarget2D(
|
||||||
graphicsDevice,
|
|
||||||
renderDimensionsX,
|
|
||||||
renderDimensionsY,
|
|
||||||
false,
|
|
||||||
SurfaceFormat.Color,
|
|
||||||
DepthFormat.None,
|
|
||||||
0,
|
|
||||||
RenderTargetUsage.PreserveContents
|
|
||||||
);
|
|
||||||
|
|
||||||
gPosition = new RenderTarget2D(
|
|
||||||
GraphicsDevice,
|
GraphicsDevice,
|
||||||
renderDimensionsX,
|
renderDimensionsX,
|
||||||
renderDimensionsY,
|
renderDimensionsY,
|
||||||
|
@ -106,7 +94,7 @@ namespace Kav
|
||||||
DepthFormat.Depth24
|
DepthFormat.Depth24
|
||||||
);
|
);
|
||||||
|
|
||||||
gNormal = new RenderTarget2D(
|
GNormal = new RenderTarget2D(
|
||||||
GraphicsDevice,
|
GraphicsDevice,
|
||||||
renderDimensionsX,
|
renderDimensionsX,
|
||||||
renderDimensionsY,
|
renderDimensionsY,
|
||||||
|
@ -115,7 +103,7 @@ namespace Kav
|
||||||
DepthFormat.None
|
DepthFormat.None
|
||||||
);
|
);
|
||||||
|
|
||||||
gAlbedo = new RenderTarget2D(
|
GAlbedo = new RenderTarget2D(
|
||||||
GraphicsDevice,
|
GraphicsDevice,
|
||||||
renderDimensionsX,
|
renderDimensionsX,
|
||||||
renderDimensionsY,
|
renderDimensionsY,
|
||||||
|
@ -124,7 +112,7 @@ namespace Kav
|
||||||
DepthFormat.None
|
DepthFormat.None
|
||||||
);
|
);
|
||||||
|
|
||||||
gMetallicRoughness = new RenderTarget2D(
|
GMetallicRoughness = new RenderTarget2D(
|
||||||
GraphicsDevice,
|
GraphicsDevice,
|
||||||
renderDimensionsX,
|
renderDimensionsX,
|
||||||
renderDimensionsY,
|
renderDimensionsY,
|
||||||
|
@ -134,10 +122,10 @@ namespace Kav
|
||||||
);
|
);
|
||||||
|
|
||||||
GBuffer = new RenderTargetBinding[4] {
|
GBuffer = new RenderTargetBinding[4] {
|
||||||
new RenderTargetBinding(gPosition),
|
new RenderTargetBinding(GPosition),
|
||||||
new RenderTargetBinding(gNormal),
|
new RenderTargetBinding(GNormal),
|
||||||
new RenderTargetBinding(gAlbedo),
|
new RenderTargetBinding(GAlbedo),
|
||||||
new RenderTargetBinding(gMetallicRoughness)
|
new RenderTargetBinding(GMetallicRoughness)
|
||||||
};
|
};
|
||||||
|
|
||||||
PointShadowCubeMap = new RenderTargetCube(
|
PointShadowCubeMap = new RenderTargetCube(
|
||||||
|
@ -175,6 +163,13 @@ namespace Kav
|
||||||
);
|
);
|
||||||
|
|
||||||
SpriteBatch = new SpriteBatch(graphicsDevice);
|
SpriteBatch = new SpriteBatch(graphicsDevice);
|
||||||
|
|
||||||
|
GBufferInstanceVertexBuffer = new DynamicVertexBuffer(
|
||||||
|
GraphicsDevice,
|
||||||
|
VertexDeclarations.GBufferInstanceDeclaration,
|
||||||
|
MAX_INSTANCE_VERTEX_COUNT,
|
||||||
|
BufferUsage.WriteOnly
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeferredRender(
|
public void DeferredRender(
|
||||||
|
@ -185,23 +180,47 @@ namespace Kav
|
||||||
IEnumerable<PointLight> pointLights,
|
IEnumerable<PointLight> pointLights,
|
||||||
DirectionalLight? directionalLight
|
DirectionalLight? directionalLight
|
||||||
) {
|
) {
|
||||||
GBufferRender(camera, modelTransforms);
|
GBufferRender(GBuffer, camera, modelTransforms);
|
||||||
|
|
||||||
GraphicsDevice.SetRenderTarget(ColorRenderTarget);
|
GraphicsDevice.SetRenderTarget(ColorRenderTarget);
|
||||||
GraphicsDevice.Clear(Color.Black);
|
GraphicsDevice.Clear(Color.Black);
|
||||||
|
|
||||||
AmbientLightRender(ambientLight);
|
AmbientLightRender(
|
||||||
|
ColorRenderTarget,
|
||||||
|
GPosition,
|
||||||
|
GAlbedo,
|
||||||
|
ambientLight
|
||||||
|
);
|
||||||
|
|
||||||
DeferredPointLightEffect.EyePosition = camera.Position;
|
DeferredPointLightEffect.EyePosition = camera.Position;
|
||||||
|
|
||||||
foreach (var pointLight in pointLights)
|
foreach (var pointLight in pointLights)
|
||||||
{
|
{
|
||||||
PointLightRender(camera, modelTransforms, pointLight);
|
PointLightRender(
|
||||||
|
ColorRenderTarget,
|
||||||
|
GPosition,
|
||||||
|
GAlbedo,
|
||||||
|
GNormal,
|
||||||
|
GMetallicRoughness,
|
||||||
|
camera,
|
||||||
|
modelTransforms,
|
||||||
|
pointLight
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (directionalLight.HasValue)
|
if (directionalLight.HasValue)
|
||||||
{
|
{
|
||||||
DirectionalLightRender(camera, modelTransforms, directionalLight.Value);
|
DirectionalLightRender(
|
||||||
|
ColorRenderTarget,
|
||||||
|
GPosition,
|
||||||
|
GAlbedo,
|
||||||
|
GNormal,
|
||||||
|
GMetallicRoughness,
|
||||||
|
camera,
|
||||||
|
modelTransforms,
|
||||||
|
directionalLight.Value,
|
||||||
|
NumShadowCascades
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphicsDevice.SetRenderTarget(renderTarget);
|
GraphicsDevice.SetRenderTarget(renderTarget);
|
||||||
|
@ -219,7 +238,7 @@ namespace Kav
|
||||||
DirectionalLight? directionalLight,
|
DirectionalLight? directionalLight,
|
||||||
TextureCube skybox
|
TextureCube skybox
|
||||||
) {
|
) {
|
||||||
GBufferRender(camera, modelTransforms);
|
GBufferRender(GBuffer, camera, modelTransforms);
|
||||||
|
|
||||||
GraphicsDevice.SetRenderTarget(ColorRenderTarget);
|
GraphicsDevice.SetRenderTarget(ColorRenderTarget);
|
||||||
GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1f, 0);
|
GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1f, 0);
|
||||||
|
@ -228,18 +247,44 @@ namespace Kav
|
||||||
DepthRender(camera, modelTransforms);
|
DepthRender(camera, modelTransforms);
|
||||||
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
||||||
|
|
||||||
AmbientLightRender(ambientLight);
|
AmbientLightRender(
|
||||||
|
ColorRenderTarget,
|
||||||
|
GPosition,
|
||||||
|
GAlbedo,
|
||||||
|
ambientLight
|
||||||
|
);
|
||||||
|
|
||||||
foreach (var pointLight in pointLights)
|
foreach (var pointLight in pointLights)
|
||||||
{
|
{
|
||||||
PointLightRender(camera, modelTransforms, pointLight);
|
PointLightRender(
|
||||||
|
ColorRenderTarget,
|
||||||
|
GPosition,
|
||||||
|
GAlbedo,
|
||||||
|
GNormal,
|
||||||
|
GMetallicRoughness,
|
||||||
|
camera,
|
||||||
|
modelTransforms,
|
||||||
|
pointLight
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (directionalLight.HasValue)
|
if (directionalLight.HasValue)
|
||||||
{
|
{
|
||||||
DirectionalLightToonRender(camera, modelTransforms, directionalLight.Value);
|
DirectionalLightToonRender(
|
||||||
|
ColorRenderTarget,
|
||||||
|
GPosition,
|
||||||
|
GAlbedo,
|
||||||
|
GNormal,
|
||||||
|
GMetallicRoughness,
|
||||||
|
camera,
|
||||||
|
modelTransforms,
|
||||||
|
directionalLight.Value,
|
||||||
|
NumShadowCascades,
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkyboxRender(camera, skybox);
|
SkyboxRender(ColorRenderTarget, camera, skybox);
|
||||||
|
|
||||||
GraphicsDevice.SetRenderTarget(renderTarget);
|
GraphicsDevice.SetRenderTarget(renderTarget);
|
||||||
SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, null, null, null, null);
|
SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, null, null, null, null);
|
||||||
|
@ -394,9 +439,11 @@ namespace Kav
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SkyboxRender(
|
private void SkyboxRender(
|
||||||
|
RenderTarget2D renderTarget,
|
||||||
PerspectiveCamera camera,
|
PerspectiveCamera camera,
|
||||||
TextureCube skybox
|
TextureCube skybox
|
||||||
) {
|
) {
|
||||||
|
GraphicsDevice.SetRenderTarget(renderTarget);
|
||||||
GraphicsDevice.RasterizerState.CullMode = CullMode.CullClockwiseFace;
|
GraphicsDevice.RasterizerState.CullMode = CullMode.CullClockwiseFace;
|
||||||
SkyboxEffect.Skybox = skybox;
|
SkyboxEffect.Skybox = skybox;
|
||||||
|
|
||||||
|
@ -425,12 +472,68 @@ namespace Kav
|
||||||
GraphicsDevice.RasterizerState.CullMode = CullMode.CullCounterClockwiseFace;
|
GraphicsDevice.RasterizerState.CullMode = CullMode.CullCounterClockwiseFace;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GBufferRender(
|
/// <summary>
|
||||||
|
/// GBuffer binding must have 4 render targets.
|
||||||
|
/// </summary>
|
||||||
|
public void InstancedGBufferRender<T>(
|
||||||
|
RenderTargetBinding[] gBuffer,
|
||||||
|
PerspectiveCamera camera,
|
||||||
|
T drawable,
|
||||||
|
int numInstances,
|
||||||
|
IEnumerable<Matrix> transforms
|
||||||
|
) where T : IIndexDrawable, IGBufferDrawable {
|
||||||
|
GraphicsDevice.SetRenderTargets(gBuffer);
|
||||||
|
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
||||||
|
GraphicsDevice.BlendState = BlendState.Opaque;
|
||||||
|
|
||||||
|
Deferred_GBufferEffect.Albedo = drawable.Albedo;
|
||||||
|
Deferred_GBufferEffect.Metallic = drawable.Metallic;
|
||||||
|
Deferred_GBufferEffect.Roughness = drawable.Roughness;
|
||||||
|
|
||||||
|
Deferred_GBufferEffect.AlbedoTexture = drawable.AlbedoTexture;
|
||||||
|
Deferred_GBufferEffect.NormalTexture = drawable.NormalTexture;
|
||||||
|
Deferred_GBufferEffect.MetallicRoughnessTexture = drawable.MetallicRoughnessTexture;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
foreach (var transform in transforms)
|
||||||
|
{
|
||||||
|
if (i >= numInstances) { break; }
|
||||||
|
GBufferInstanceVertices[i].World = transform;
|
||||||
|
GBufferInstanceVertices[i].WorldInverseTranspose = Matrix.Transpose(Matrix.Invert(transform));
|
||||||
|
GBufferInstanceVertices[i].WorldViewProjection = transform * camera.View * camera.Projection;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
GBufferInstanceVertexBuffer.SetData(
|
||||||
|
GBufferInstanceVertices,
|
||||||
|
0,
|
||||||
|
numInstances,
|
||||||
|
SetDataOptions.Discard
|
||||||
|
);
|
||||||
|
|
||||||
|
GraphicsDevice.SetVertexBuffers(
|
||||||
|
drawable.VertexBuffer,
|
||||||
|
new VertexBufferBinding(GBufferInstanceVertexBuffer, 0, 1)
|
||||||
|
);
|
||||||
|
GraphicsDevice.Indices = drawable.IndexBuffer;
|
||||||
|
|
||||||
|
GraphicsDevice.DrawInstancedPrimitives(
|
||||||
|
PrimitiveType.TriangleList,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
drawable.VertexBuffer.VertexCount,
|
||||||
|
0,
|
||||||
|
drawable.IndexBuffer.IndexCount / 3,
|
||||||
|
numInstances
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GBufferRender(
|
||||||
|
RenderTargetBinding[] gBuffer,
|
||||||
PerspectiveCamera camera,
|
PerspectiveCamera camera,
|
||||||
IEnumerable<(Model, Matrix)> modelTransforms
|
IEnumerable<(Model, Matrix)> modelTransforms
|
||||||
) {
|
) {
|
||||||
GraphicsDevice.SetRenderTargets(GBuffer);
|
GraphicsDevice.SetRenderTargets(gBuffer);
|
||||||
GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1f, 0);
|
|
||||||
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
||||||
GraphicsDevice.BlendState = BlendState.Opaque;
|
GraphicsDevice.BlendState = BlendState.Opaque;
|
||||||
|
|
||||||
|
@ -475,9 +578,13 @@ namespace Kav
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AmbientLightRender(AmbientLight ambientLight)
|
public void AmbientLightRender(
|
||||||
{
|
RenderTarget2D renderTarget,
|
||||||
GraphicsDevice.SetRenderTarget(ColorRenderTarget);
|
Texture2D gPosition,
|
||||||
|
Texture2D gAlbedo,
|
||||||
|
AmbientLight ambientLight
|
||||||
|
) {
|
||||||
|
GraphicsDevice.SetRenderTarget(renderTarget);
|
||||||
GraphicsDevice.BlendState = BlendState.Opaque;
|
GraphicsDevice.BlendState = BlendState.Opaque;
|
||||||
|
|
||||||
DeferredAmbientLightEffect.GPosition = gPosition;
|
DeferredAmbientLightEffect.GPosition = gPosition;
|
||||||
|
@ -492,14 +599,19 @@ namespace Kav
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PointLightRender(
|
public void PointLightRender(
|
||||||
|
RenderTarget2D renderTarget,
|
||||||
|
Texture2D gPosition,
|
||||||
|
Texture2D gAlbedo,
|
||||||
|
Texture2D gNormal,
|
||||||
|
Texture2D gMetallicRoughness,
|
||||||
PerspectiveCamera camera,
|
PerspectiveCamera camera,
|
||||||
IEnumerable<(Model, Matrix)> modelTransforms,
|
IEnumerable<(Model, Matrix)> modelTransforms,
|
||||||
PointLight pointLight
|
PointLight pointLight
|
||||||
) {
|
) {
|
||||||
RenderPointShadows(camera, modelTransforms, pointLight);
|
RenderPointShadows(camera, modelTransforms, pointLight);
|
||||||
|
|
||||||
GraphicsDevice.SetRenderTarget(ColorRenderTarget);
|
GraphicsDevice.SetRenderTarget(renderTarget);
|
||||||
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
||||||
GraphicsDevice.BlendState = BlendState.Additive;
|
GraphicsDevice.BlendState = BlendState.Additive;
|
||||||
|
|
||||||
|
@ -523,28 +635,38 @@ namespace Kav
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DirectionalLightRender(
|
public void DirectionalLightRender(
|
||||||
|
RenderTarget2D renderTarget,
|
||||||
|
Texture2D gPosition,
|
||||||
|
Texture2D gAlbedo,
|
||||||
|
Texture2D gNormal,
|
||||||
|
Texture2D gMetallicRoughness,
|
||||||
PerspectiveCamera camera,
|
PerspectiveCamera camera,
|
||||||
IEnumerable<(Model, Matrix)> modelTransforms,
|
IEnumerable<(Model, Matrix)> modelTransforms,
|
||||||
DirectionalLight directionalLight
|
DirectionalLight directionalLight,
|
||||||
|
int numShadowCascades
|
||||||
) {
|
) {
|
||||||
RenderDirectionalShadows(camera, modelTransforms, directionalLight, DeferredDirectionalLightEffect);
|
RenderDirectionalShadows(camera, modelTransforms, directionalLight, DeferredDirectionalLightEffect);
|
||||||
|
|
||||||
|
GraphicsDevice.SetRenderTarget(renderTarget);
|
||||||
|
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
||||||
|
GraphicsDevice.BlendState = BlendState.Additive;
|
||||||
|
|
||||||
DeferredDirectionalLightEffect.GPosition = gPosition;
|
DeferredDirectionalLightEffect.GPosition = gPosition;
|
||||||
DeferredDirectionalLightEffect.GAlbedo = gAlbedo;
|
DeferredDirectionalLightEffect.GAlbedo = gAlbedo;
|
||||||
DeferredDirectionalLightEffect.GNormal = gNormal;
|
DeferredDirectionalLightEffect.GNormal = gNormal;
|
||||||
DeferredDirectionalLightEffect.GMetallicRoughness = gMetallicRoughness;
|
DeferredDirectionalLightEffect.GMetallicRoughness = gMetallicRoughness;
|
||||||
|
|
||||||
DeferredDirectionalLightEffect.ShadowMapOne = ShadowRenderTargets[0];
|
DeferredDirectionalLightEffect.ShadowMapOne = ShadowRenderTargets[0];
|
||||||
if (NumShadowCascades > 1)
|
if (numShadowCascades > 1)
|
||||||
{
|
{
|
||||||
DeferredDirectionalLightEffect.ShadowMapTwo = ShadowRenderTargets[1];
|
DeferredDirectionalLightEffect.ShadowMapTwo = ShadowRenderTargets[1];
|
||||||
}
|
}
|
||||||
if (NumShadowCascades > 2)
|
if (numShadowCascades > 2)
|
||||||
{
|
{
|
||||||
DeferredDirectionalLightEffect.ShadowMapThree = ShadowRenderTargets[2];
|
DeferredDirectionalLightEffect.ShadowMapThree = ShadowRenderTargets[2];
|
||||||
}
|
}
|
||||||
if (NumShadowCascades > 3)
|
if (numShadowCascades > 3)
|
||||||
{
|
{
|
||||||
DeferredDirectionalLightEffect.ShadowMapFour = ShadowRenderTargets[3];
|
DeferredDirectionalLightEffect.ShadowMapFour = ShadowRenderTargets[3];
|
||||||
}
|
}
|
||||||
|
@ -556,9 +678,6 @@ namespace Kav
|
||||||
DeferredDirectionalLightEffect.ViewMatrix = camera.View;
|
DeferredDirectionalLightEffect.ViewMatrix = camera.View;
|
||||||
DeferredDirectionalLightEffect.EyePosition = camera.Position;
|
DeferredDirectionalLightEffect.EyePosition = camera.Position;
|
||||||
|
|
||||||
GraphicsDevice.SetRenderTarget(ColorRenderTarget);
|
|
||||||
GraphicsDevice.BlendState = BlendState.Additive;
|
|
||||||
|
|
||||||
foreach (EffectPass pass in DeferredDirectionalLightEffect.CurrentTechnique.Passes)
|
foreach (EffectPass pass in DeferredDirectionalLightEffect.CurrentTechnique.Passes)
|
||||||
{
|
{
|
||||||
pass.Apply();
|
pass.Apply();
|
||||||
|
@ -568,13 +687,20 @@ namespace Kav
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DirectionalLightToonRender(
|
private void DirectionalLightToonRender(
|
||||||
|
RenderTarget2D renderTarget,
|
||||||
|
Texture2D gPosition,
|
||||||
|
Texture2D gAlbedo,
|
||||||
|
Texture2D gNormal,
|
||||||
|
Texture2D gMetallicRoughness,
|
||||||
PerspectiveCamera camera,
|
PerspectiveCamera camera,
|
||||||
IEnumerable<(Model, Matrix)> modelTransforms,
|
IEnumerable<(Model, Matrix)> modelTransforms,
|
||||||
DirectionalLight directionalLight
|
DirectionalLight directionalLight,
|
||||||
|
int numShadowCascades,
|
||||||
|
bool ditheredShadows
|
||||||
) {
|
) {
|
||||||
RenderDirectionalShadows(camera, modelTransforms, directionalLight, Deferred_ToonEffect);
|
RenderDirectionalShadows(camera, modelTransforms, directionalLight, Deferred_ToonEffect);
|
||||||
|
|
||||||
GraphicsDevice.SetRenderTarget(ColorRenderTarget);
|
GraphicsDevice.SetRenderTarget(renderTarget);
|
||||||
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
||||||
GraphicsDevice.BlendState = BlendState.Additive;
|
GraphicsDevice.BlendState = BlendState.Additive;
|
||||||
|
|
||||||
|
@ -583,7 +709,7 @@ namespace Kav
|
||||||
Deferred_ToonEffect.GNormal = gNormal;
|
Deferred_ToonEffect.GNormal = gNormal;
|
||||||
Deferred_ToonEffect.GMetallicRoughness = gMetallicRoughness;
|
Deferred_ToonEffect.GMetallicRoughness = gMetallicRoughness;
|
||||||
|
|
||||||
Deferred_ToonEffect.DitheredShadows = false;
|
Deferred_ToonEffect.DitheredShadows = ditheredShadows;
|
||||||
|
|
||||||
Deferred_ToonEffect.EyePosition = camera.Position;
|
Deferred_ToonEffect.EyePosition = camera.Position;
|
||||||
|
|
||||||
|
@ -592,15 +718,15 @@ namespace Kav
|
||||||
directionalLight.Color.ToVector3() * directionalLight.Intensity;
|
directionalLight.Color.ToVector3() * directionalLight.Intensity;
|
||||||
|
|
||||||
Deferred_ToonEffect.ShadowMapOne = ShadowRenderTargets[0];
|
Deferred_ToonEffect.ShadowMapOne = ShadowRenderTargets[0];
|
||||||
if (NumShadowCascades > 1)
|
if (numShadowCascades > 1)
|
||||||
{
|
{
|
||||||
Deferred_ToonEffect.ShadowMapTwo = ShadowRenderTargets[1];
|
Deferred_ToonEffect.ShadowMapTwo = ShadowRenderTargets[1];
|
||||||
}
|
}
|
||||||
if (NumShadowCascades > 2)
|
if (numShadowCascades > 2)
|
||||||
{
|
{
|
||||||
Deferred_ToonEffect.ShadowMapThree = ShadowRenderTargets[2];
|
Deferred_ToonEffect.ShadowMapThree = ShadowRenderTargets[2];
|
||||||
}
|
}
|
||||||
if (NumShadowCascades > 3)
|
if (numShadowCascades > 3)
|
||||||
{
|
{
|
||||||
Deferred_ToonEffect.ShadowMapFour = ShadowRenderTargets[3];
|
Deferred_ToonEffect.ShadowMapFour = ShadowRenderTargets[3];
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Kav
|
||||||
|
{
|
||||||
|
public static class VertexDeclarations
|
||||||
|
{
|
||||||
|
public static VertexDeclaration GBufferInstanceDeclaration = new VertexDeclaration
|
||||||
|
(
|
||||||
|
new VertexElement(0, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, 0),
|
||||||
|
new VertexElement(16, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, 1),
|
||||||
|
new VertexElement(32, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, 2),
|
||||||
|
new VertexElement(48, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, 3),
|
||||||
|
new VertexElement(64, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, 4),
|
||||||
|
new VertexElement(80, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, 5),
|
||||||
|
new VertexElement(96, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, 6),
|
||||||
|
new VertexElement(112, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, 7),
|
||||||
|
new VertexElement(128, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, 8),
|
||||||
|
new VertexElement(144, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, 9),
|
||||||
|
new VertexElement(160, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, 10),
|
||||||
|
new VertexElement(176, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, 11)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Kav
|
||||||
|
{
|
||||||
|
public struct GBufferInstanceVertex : IVertexType
|
||||||
|
{
|
||||||
|
VertexDeclaration IVertexType.VertexDeclaration
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return VertexDeclarations.GBufferInstanceDeclaration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Matrix World { get; set; }
|
||||||
|
public Matrix WorldInverseTranspose { get; set; }
|
||||||
|
public Matrix WorldViewProjection { get; set; }
|
||||||
|
|
||||||
|
public static readonly VertexDeclaration VertexDeclaration;
|
||||||
|
|
||||||
|
public GBufferInstanceVertex(
|
||||||
|
Matrix world,
|
||||||
|
Matrix worldInverseTranspose,
|
||||||
|
Matrix worldViewProjection
|
||||||
|
) {
|
||||||
|
World = world;
|
||||||
|
WorldInverseTranspose = worldInverseTranspose;
|
||||||
|
WorldViewProjection = worldViewProjection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue