single triangle renderer optimization

pull/2/head
cosmonaut 2020-09-17 15:47:23 -07:00
parent 7062992d9b
commit 10f3d9cd98
3 changed files with 110 additions and 9 deletions

Binary file not shown.

View File

@ -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();
}
}

View File

@ -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<PointLight> 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,