From 9a7fb75ec584ec77f209dc20fd309738a610f8ee Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 8 Dec 2020 16:37:22 -0800 Subject: [PATCH] refactor for reusing instance buffers --- Renderer.cs | 138 +++++++++++++++++++++++----------------------------- 1 file changed, 62 insertions(+), 76 deletions(-) diff --git a/Renderer.cs b/Renderer.cs index d85af09..9b7b0c0 100644 --- a/Renderer.cs +++ b/Renderer.cs @@ -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( - GraphicsDevice graphicsDevice, - T drawable, + public static int FillInstanceVertexBuffer( IEnumerable 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( + public static void RenderInstanced( 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 /// /// GBuffer binding must have 4 render targets. + /// Assumes that vertex buffer has been filled. /// public void RenderGBufferInstanced( RenderTargetBinding[] gBuffer, RenderTarget2D depthBuffer, PerspectiveCamera camera, T drawable, - IEnumerable 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( DirectionalShadowMapData shadowMapData, T drawable, - IEnumerable 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 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( RenderTargetCube pointShadowCubeMap, - PerspectiveCamera camera, T drawable, - IEnumerable 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 + ); } }