From 10f3d9cd98b53f16bc39ab7fa56a7bff93558da0 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Thu, 17 Sep 2020 15:47:23 -0700 Subject: [PATCH] single triangle renderer optimization --- Effects/FXB/DeferredPBREffect.fxb | Bin 52564 -> 52792 bytes Effects/HLSL/DeferredPBREffect.fx | 17 +++++ Renderer.cs | 102 +++++++++++++++++++++++++++--- 3 files changed, 110 insertions(+), 9 deletions(-) diff --git a/Effects/FXB/DeferredPBREffect.fxb b/Effects/FXB/DeferredPBREffect.fxb index 5934933a7e19ec1cde2840c6542e7438fa47a5c7..f06f5aabc8421dd6bd589e0c45af7e7fb941028d 100644 GIT binary patch delta 259 zcmcaIi+RT!W>!Yd|Nn9}vTAcN3QTrn6lUa^tjlH2%E7?Ez`Hq`5R&AkYAcsQ~e02$#VD$hHAuRv@2!@=R`XM#jw-xz8VPgvvAg2Lc#-35db` z@BhF5A`H$Uj!rT_t};{%L_vW9NW5(FTp@iAc?JfM?F|eJ{1ZTIpfwGQP&QQj0YaSl c0nph%_52SQ7@kZ3u^AaaVoxSao^xgg01@yk^#A|> delta 98 zcmdlnhxy7ZW>!Yd|NlZZvTAcN@=tbT6rY^HCBw?jz`($>xsi*RQP+hF$OZyNAhtnb jPX>!JFlYe9RDhTj$Y+~;klUP*Ve?P!^9LrkoZSKdqNx(O diff --git a/Effects/HLSL/DeferredPBREffect.fx b/Effects/HLSL/DeferredPBREffect.fx index c64a9f2..2f9f3a1 100644 --- a/Effects/HLSL/DeferredPBREffect.fx +++ b/Effects/HLSL/DeferredPBREffect.fx @@ -25,12 +25,28 @@ MATRIX_CONSTANTS END_CONSTANTS +struct VertexInput +{ + float4 Position : POSITION; + float2 TexCoord : TEXCOORD; +}; + struct PixelInput { float4 Position : SV_POSITION; float2 TexCoord : TEXCOORD0; }; +PixelInput main_vs(VertexInput input) +{ + PixelInput output; + + output.Position = input.Position; + output.TexCoord = input.TexCoord; + + return output; +} + // Pixel Shader float3 FresnelSchlick(float cosTheta, float3 F0) @@ -195,6 +211,7 @@ Technique DeferredPBR { Pass { + VertexShader = compile vs_3_0 main_vs(); PixelShader = compile ps_3_0 main_ps(); } } diff --git a/Renderer.cs b/Renderer.cs index d5d136f..210aed8 100644 --- a/Renderer.cs +++ b/Renderer.cs @@ -10,7 +10,10 @@ namespace Kav private int RenderDimensionsX { get; } private int RenderDimensionsY { get; } + private VertexBuffer FullscreenTriangle { get; } private RenderTarget2D ShadowRenderTarget { get; } + + private DeferredPBREffect DeferredPBREffect { get; } private SimpleDepthEffect SimpleDepthEffect { get; } private RenderTarget2D gPosition { get; } @@ -21,8 +24,6 @@ namespace Kav private RenderTargetBinding[] GBuffer { get; } - private DeferredPBREffect DeferredPBREffect { get; } - private SpriteBatch SpriteBatch { get; } public Renderer(GraphicsDevice graphicsDevice, int renderDimensionsX, int renderDimensionsY) @@ -92,6 +93,13 @@ namespace Kav SimpleDepthEffect = new SimpleDepthEffect(GraphicsDevice); DeferredPBREffect = new DeferredPBREffect(GraphicsDevice); + FullscreenTriangle = new VertexBuffer(GraphicsDevice, typeof(VertexPositionTexture), 3, BufferUsage.WriteOnly); + FullscreenTriangle.SetData(new VertexPositionTexture[3] { + new VertexPositionTexture(new Vector3(-1, -1, 0), new Vector2(0, 0)), + new VertexPositionTexture(new Vector3(-1, 3, 0), new Vector2(0, -2)), + new VertexPositionTexture(new Vector3(3, -1, 0), new Vector2(2, 0)) + }); + SpriteBatch = new SpriteBatch(GraphicsDevice); GraphicsDevice.SetRenderTarget(deferredRenderTarget); @@ -103,9 +111,10 @@ namespace Kav Camera camera, IEnumerable<(Model, Matrix)> modelTransforms, IEnumerable pointLights, - DirectionalLight directionalLight + DirectionalLight directionalLight, + int numCascades ) { - ShadowMapRender(camera, modelTransforms, directionalLight); + ShadowMapRender(camera, modelTransforms, directionalLight, numCascades); GraphicsDevice.SetRenderTargets(GBuffer); GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1f, 0); @@ -166,13 +175,25 @@ namespace Kav DeferredPBREffect.DirectionalLightColor = directionalLight.Color.ToVector3() * directionalLight.Intensity; DeferredPBREffect.DirectionalLightDirection = directionalLight.Direction; - SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, null, null, DeferredPBREffect); - SpriteBatch.Draw(deferredRenderTarget, Vector2.Zero, Color.White); - SpriteBatch.End(); + + foreach (EffectPass pass in DeferredPBREffect.CurrentTechnique.Passes) + { + pass.Apply(); + GraphicsDevice.SetVertexBuffer(FullscreenTriangle); + GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1); + } + + // SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, null, null, DeferredPBREffect); + // SpriteBatch.Draw(deferredRenderTarget, Vector2.Zero, Color.White); + // SpriteBatch.End(); } - public void ShadowMapRender(Camera camera, IEnumerable<(Model, Matrix)> modelTransforms, DirectionalLight directionalLight) - { + public void ShadowMapRender( + Camera camera, + IEnumerable<(Model, Matrix)> modelTransforms, + DirectionalLight directionalLight, + int numCascades + ) { GraphicsDevice.SetRenderTarget(ShadowRenderTarget); GraphicsDevice.Clear(Color.White); GraphicsDevice.DepthStencilState = DepthStencilState.Default; @@ -240,6 +261,69 @@ namespace Kav } } + private void RenderShadowMap(Camera camera, IEnumerable<(Model, Matrix)> modelTransforms, DirectionalLight directionalLight) + { + var right = Vector3.Cross(Vector3.Up, directionalLight.Direction); + var up = Vector3.Cross(directionalLight.Direction, right); + var cameraBoundingFrustum = new BoundingFrustum(camera.View * camera.Projection); + Vector3[] frustumCorners = cameraBoundingFrustum.GetCorners(); + + Vector3 frustumCenter = Vector3.Zero; + for (var i = 0; i < frustumCorners.Length; i++) + { + frustumCenter += frustumCorners[i]; + } + frustumCenter /= 8f; + + var lightView = Matrix.CreateLookAt(frustumCenter, frustumCenter - directionalLight.Direction, camera.View.Right); + + for (var i = 0; i < frustumCorners.Length; i++) + { + frustumCorners[i] = Vector3.Transform(frustumCorners[i], lightView); + } + + BoundingBox lightBox = BoundingBox.CreateFromPoints(frustumCorners); + Vector3 lightPosition = frustumCenter + directionalLight.Direction * -lightBox.Min.Z; + + SimpleDepthEffect.View = Matrix.CreateLookAt(lightPosition, frustumCenter, camera.View.Right); + SimpleDepthEffect.Projection = Matrix.CreateOrthographicOffCenter( + lightBox.Min.X, + lightBox.Max.X, + lightBox.Min.Y, + lightBox.Max.Y, + 0, + lightBox.Max.Z - lightBox.Min.Z + ); + + foreach (var (model, transform) in modelTransforms) + { + foreach (var modelMesh in model.Meshes) + { + foreach (var meshPart in modelMesh.MeshParts) + { + GraphicsDevice.SetVertexBuffer(meshPart.VertexBuffer); + GraphicsDevice.Indices = meshPart.IndexBuffer; + + SimpleDepthEffect.Model = transform; + + foreach (var pass in SimpleDepthEffect.CurrentTechnique.Passes) + { + pass.Apply(); + + GraphicsDevice.DrawIndexedPrimitives( + PrimitiveType.TriangleList, + 0, + 0, + meshPart.VertexBuffer.VertexCount, + 0, + meshPart.Triangles.Length + ); + } + } + } + } + } + public void Render( Camera camera, IEnumerable<(Model, Matrix)> modelTransforms,