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