refactor for reusing instance buffers

palette_crush
cosmonaut 2020-12-08 16:37:22 -08:00
parent 0c576668cb
commit 9a7fb75ec5
1 changed files with 62 additions and 76 deletions

View File

@ -8,8 +8,6 @@ namespace Kav
{
public class Renderer
{
private const int MAX_INSTANCE_VERTEX_COUNT = 1000000;
private GraphicsDevice GraphicsDevice { get; }
private VertexBuffer FullscreenTriangle { get; }
@ -24,15 +22,13 @@ namespace Kav
private SimpleDepthEffect SimpleDepthEffect { get; }
private SimpleDepthEffectInstanced SimpleDepthEffectInstanced { get; }
private LinearDepthEffect LinearDepthEffect { get; }
private LinearDepthEffectInstanced LinearDepthEffectInstanced { get; }
private Effect ToneMapEffect { get; }
private SkyboxEffect SkyboxEffect { get; }
private DiffuseLitSpriteEffect DiffuseLitSpriteEffect { get; }
private Kav.Model UnitCube { get; }
private DynamicVertexBuffer PositionInstanceVertexBuffer { get; }
private readonly PositionInstanceVertex[] PositionInstanceVertices = new PositionInstanceVertex[MAX_INSTANCE_VERTEX_COUNT];
public Renderer(
GraphicsDevice graphicsDevice
) {
@ -41,6 +37,8 @@ namespace Kav
SimpleDepthEffect = new SimpleDepthEffect(GraphicsDevice);
SimpleDepthEffectInstanced = new SimpleDepthEffectInstanced(GraphicsDevice);
LinearDepthEffect = new LinearDepthEffect(GraphicsDevice);
LinearDepthEffectInstanced = new LinearDepthEffectInstanced(GraphicsDevice);
DeferredPBREffect = new DeferredPBREffect(GraphicsDevice);
Deferred_GBufferEffect = new DeferredPBR_GBufferEffect(GraphicsDevice);
@ -63,13 +61,21 @@ namespace Kav
GraphicsDevice,
Smuggler.Importer.ImportGLB(GraphicsDevice, new MemoryStream(Resources.UnitCubeModel))
);
}
PositionInstanceVertexBuffer = new DynamicVertexBuffer(
GraphicsDevice,
public static (PositionInstanceVertex[], DynamicVertexBuffer) CreatePositionVertexBuffer(
GraphicsDevice graphicsDevice,
int instanceVertexCount
) {
var positionData = new PositionInstanceVertex[instanceVertexCount];
var vertexBuffer = new DynamicVertexBuffer(
graphicsDevice,
VertexDeclarations.PositionInstanceDeclaration,
MAX_INSTANCE_VERTEX_COUNT,
instanceVertexCount,
BufferUsage.WriteOnly
);
return (positionData, vertexBuffer);
}
public static RenderTargetCube CreateShadowCubeMap(
@ -251,13 +257,11 @@ namespace Kav
}
}
public static int FillAndSetBuffersForInstancing<T, V>(
GraphicsDevice graphicsDevice,
T drawable,
public static int FillInstanceVertexBuffer<V>(
IEnumerable<Matrix> transforms,
V[] vertexData,
DynamicVertexBuffer dynamicVertexBuffer
) where T : ICullable, IIndexDrawable where V : struct, IVertexType, IHasTranslation
) where V : struct, IVertexType, IHasTranslation
{
int numInstances = 0;
foreach (var transform in transforms)
@ -275,22 +279,22 @@ namespace Kav
SetDataOptions.Discard
);
graphicsDevice.SetVertexBuffers(
drawable.VertexBuffer,
new VertexBufferBinding(dynamicVertexBuffer, 0, 1)
);
graphicsDevice.Indices = drawable.IndexBuffer;
return numInstances;
}
public static void RenderInstanced<T, U>(
public static void RenderInstanced<T>(
GraphicsDevice graphicsDevice,
T drawable,
U effect,
int numInstances
) where T : ICullable, IIndexDrawable where U : Effect
{
VertexBuffer instanceVertexBuffer,
int numInstances,
Effect effect
) where T : IIndexDrawable {
graphicsDevice.SetVertexBuffers(
drawable.VertexBuffer,
new VertexBufferBinding(instanceVertexBuffer, 0, 1)
);
graphicsDevice.Indices = drawable.IndexBuffer;
foreach (var pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
@ -367,14 +371,16 @@ namespace Kav
/// <summary>
/// GBuffer binding must have 4 render targets.
/// Assumes that vertex buffer has been filled.
/// </summary>
public void RenderGBufferInstanced<T>(
RenderTargetBinding[] gBuffer,
RenderTarget2D depthBuffer,
PerspectiveCamera camera,
T drawable,
IEnumerable<Matrix> transforms
) where T : ICullable, IIndexDrawable, IGBufferDrawable {
VertexBuffer instanceVertexBuffer,
int numInstances
) where T : IGBufferDrawable, IIndexDrawable {
GraphicsDevice.SetRenderTargets(gBuffer);
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
GraphicsDevice.BlendState = BlendState.Opaque;
@ -392,21 +398,12 @@ namespace Kav
Deferred_GBufferEffect.View = camera.View;
Deferred_GBufferEffect.Projection = camera.Projection;
var numInstances = FillAndSetBuffersForInstancing(
GraphicsDevice,
drawable,
transforms,
PositionInstanceVertices,
PositionInstanceVertexBuffer
);
if (numInstances == 0) { return; }
RenderInstanced(
GraphicsDevice,
drawable,
Deferred_GBufferEffect,
numInstances
drawable,
instanceVertexBuffer,
numInstances,
Deferred_GBufferEffect
);
// re-render to get depth
@ -418,8 +415,9 @@ namespace Kav
RenderInstanced(
GraphicsDevice,
drawable,
SimpleDepthEffectInstanced,
numInstances
instanceVertexBuffer,
numInstances,
SimpleDepthEffectInstanced
);
}
@ -717,8 +715,9 @@ namespace Kav
public void RenderDirectionalShadowsInstanced<T>(
DirectionalShadowMapData shadowMapData,
T drawable,
IEnumerable<Matrix> transforms
) where T : ICullable, IIndexDrawable
VertexBuffer instanceVertexBuffer,
int numInstances
) where T : IIndexDrawable
{
// render the individual shadow cascades
for (var i = 0; i < shadowMapData.NumShadowCascades; i++)
@ -727,7 +726,8 @@ namespace Kav
shadowMapData,
i,
drawable,
transforms
instanceVertexBuffer,
numInstances
);
}
}
@ -736,8 +736,9 @@ namespace Kav
DirectionalShadowMapData shadowMapData,
int shadowCascadeIndex,
T drawable,
IEnumerable<Matrix> transforms
) where T : ICullable, IIndexDrawable
VertexBuffer instanceVertexBuffer,
int numInstances
) where T : IIndexDrawable
{
GraphicsDevice.SetRenderTarget(shadowMapData.ShadowMaps[shadowCascadeIndex]);
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
@ -746,19 +747,12 @@ namespace Kav
SimpleDepthEffectInstanced.View = shadowMapData.LightSpaceViews[shadowCascadeIndex];
SimpleDepthEffectInstanced.Projection = shadowMapData.LightSpaceProjections[shadowCascadeIndex];
var numInstances = FillAndSetBuffersForInstancing(
GraphicsDevice,
drawable,
transforms,
PositionInstanceVertices,
PositionInstanceVertexBuffer
);
RenderInstanced(
GraphicsDevice,
drawable,
SimpleDepthEffectInstanced,
numInstances
instanceVertexBuffer,
numInstances,
SimpleDepthEffectInstanced
);
}
@ -841,9 +835,9 @@ namespace Kav
public void RenderPointShadowMapInstanced<T>(
RenderTargetCube pointShadowCubeMap,
PerspectiveCamera camera,
T drawable,
IEnumerable<Matrix> modelTransforms,
VertexBuffer instanceVertexBuffer,
int numInstances,
PointLight pointLight
) where T : ICullable, IIndexDrawable
{
@ -894,36 +888,28 @@ namespace Kav
break;
}
LinearDepthEffect.View = Matrix.CreateLookAt(
LinearDepthEffectInstanced.View = Matrix.CreateLookAt(
pointLight.Position,
pointLight.Position + targetDirection,
targetUpDirection
);
LinearDepthEffect.Projection = Matrix.CreatePerspectiveFieldOfView(
LinearDepthEffectInstanced.Projection = Matrix.CreatePerspectiveFieldOfView(
MathHelper.PiOver2,
1,
0.1f,
25f // FIXME: magic value
);
LinearDepthEffect.FarPlane = 25f;
LinearDepthEffect.LightPosition = pointLight.Position;
LinearDepthEffectInstanced.FarPlane = 25f;
LinearDepthEffectInstanced.LightPosition = pointLight.Position;
// TODO: set up instancing
// var numInstances = FillAndSetBuffersForInstancing(
// GraphicsDevice,
// camera,
// drawable,
// transforms,
// VertexPos
// );
// RenderInstanced(
// GraphicsDevice,
// camera,
// modelTransforms,
// LinearDepthEffect
// );
RenderInstanced(
GraphicsDevice,
drawable,
instanceVertexBuffer,
numInstances,
LinearDepthEffectInstanced
);
}
}