From 84601379b56c5a665e45c34737e02196eee84a36 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Mon, 7 Dec 2020 20:10:27 -0800 Subject: [PATCH] major API refactor --- EffectInterfaces/IHasWorldMatrix.cs | 9 + Effects/LinearDepthEffect.cs | 24 +- Effects/SimpleDepthEffect.cs | 63 +++- Renderer.cs | 444 +++++++++++++--------------- Vertices/GBufferInstanceVertex.cs | 2 +- 5 files changed, 282 insertions(+), 260 deletions(-) create mode 100644 EffectInterfaces/IHasWorldMatrix.cs diff --git a/EffectInterfaces/IHasWorldMatrix.cs b/EffectInterfaces/IHasWorldMatrix.cs new file mode 100644 index 0000000..7f87b42 --- /dev/null +++ b/EffectInterfaces/IHasWorldMatrix.cs @@ -0,0 +1,9 @@ +using Microsoft.Xna.Framework; + +namespace Kav +{ + public interface IHasWorldMatrix + { + Matrix World { get; set; } + } +} diff --git a/Effects/LinearDepthEffect.cs b/Effects/LinearDepthEffect.cs index 2a6a76a..5b62977 100644 --- a/Effects/LinearDepthEffect.cs +++ b/Effects/LinearDepthEffect.cs @@ -3,28 +3,28 @@ using Microsoft.Xna.Framework.Graphics; namespace Kav { - public class LinearDepthEffect : Effect + public class LinearDepthEffect : Effect, IHasWorldMatrix { - EffectParameter modelParam; - EffectParameter modelViewProjectionParam; + EffectParameter worldParam; + EffectParameter worldViewProjectionParam; EffectParameter lightPositionParam; EffectParameter farPlaneParam; EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All; - Matrix model; + Matrix world; Matrix view; Matrix projection; public Vector3 LightPosition { get; set; } public float FarPlane { get; set; } - public Matrix Model + public Matrix World { - get { return model; } + get { return world; } set { - model = value; + world = value; dirtyFlags |= EffectDirtyFlags.World; dirtyFlags |= EffectDirtyFlags.WorldViewProj; } @@ -60,16 +60,16 @@ namespace Kav if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0) { Matrix.Multiply(ref view, ref projection, out Matrix viewProjection); - Matrix.Multiply(ref model, ref viewProjection, out Matrix worldViewProj); + Matrix.Multiply(ref world, ref viewProjection, out Matrix worldViewProj); - modelViewProjectionParam.SetValue(worldViewProj); + worldViewProjectionParam.SetValue(worldViewProj); dirtyFlags &= ~EffectDirtyFlags.WorldViewProj; } if ((dirtyFlags & EffectDirtyFlags.World) != 0) { - modelParam.SetValue(model); + worldParam.SetValue(world); dirtyFlags &= ~EffectDirtyFlags.World; } @@ -80,8 +80,8 @@ namespace Kav private void CacheEffectParameters() { - modelParam = Parameters["Model"]; - modelViewProjectionParam = Parameters["ModelViewProjection"]; + worldParam = Parameters["Model"]; + worldViewProjectionParam = Parameters["ModelViewProjection"]; lightPositionParam = Parameters["LightPosition"]; farPlaneParam = Parameters["FarPlane"]; diff --git a/Effects/SimpleDepthEffect.cs b/Effects/SimpleDepthEffect.cs index 1854e3c..200d743 100644 --- a/Effects/SimpleDepthEffect.cs +++ b/Effects/SimpleDepthEffect.cs @@ -3,23 +3,26 @@ using Microsoft.Xna.Framework.Graphics; namespace Kav { - public class SimpleDepthEffect : Effect + public class SimpleDepthEffect : Effect, IHasWorldMatrix { - EffectParameter modelViewProjectionParam; + EffectParameter worldParam; + EffectParameter viewProjectionParam; + EffectParameter vertexShaderIndexParam; - Matrix model; + Matrix world; Matrix view; Matrix projection; + bool hardwareInstancingEnabled = false; EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All; - public Matrix Model + public Matrix World { - get { return model; } + get { return world; } set { - model = value; - dirtyFlags |= EffectDirtyFlags.WorldViewProj; + world = value; + dirtyFlags |= EffectDirtyFlags.World; } } @@ -29,7 +32,7 @@ namespace Kav set { view = value; - dirtyFlags |= EffectDirtyFlags.WorldViewProj; + dirtyFlags |= EffectDirtyFlags.ViewProj; } } @@ -39,7 +42,20 @@ namespace Kav set { projection = value; - dirtyFlags |= EffectDirtyFlags.WorldViewProj; + dirtyFlags |= EffectDirtyFlags.ViewProj; + } + } + + public bool HardwareInstancingEnabled + { + get { return hardwareInstancingEnabled; } + set + { + if (value != hardwareInstancingEnabled) + { + hardwareInstancingEnabled = value; + dirtyFlags |= EffectDirtyFlags.VertexShaderIndex; + } } } @@ -50,20 +66,39 @@ namespace Kav protected override void OnApply() { - if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0) + if ((dirtyFlags & EffectDirtyFlags.World) != 0) + { + worldParam.SetValue(world); + + dirtyFlags &= ~EffectDirtyFlags.World; + } + + if ((dirtyFlags & EffectDirtyFlags.ViewProj) != 0) { Matrix.Multiply(ref view, ref projection, out Matrix viewProjection); - Matrix.Multiply(ref model, ref viewProjection, out Matrix worldViewProj); + viewProjectionParam.SetValue(viewProjection); - modelViewProjectionParam.SetValue(worldViewProj); + dirtyFlags &= ~EffectDirtyFlags.ViewProj; + } - dirtyFlags &= ~EffectDirtyFlags.WorldViewProj; + if ((dirtyFlags & EffectDirtyFlags.VertexShaderIndex) != 0) + { + int vertexShaderIndex = 0; + + if (hardwareInstancingEnabled) + { + vertexShaderIndex = 1; + } + + vertexShaderIndexParam.SetValue(vertexShaderIndex); } } private void CacheEffectParameters() { - modelViewProjectionParam = Parameters["ModelViewProjection"]; + worldParam = Parameters["World"]; + viewProjectionParam = Parameters["ViewProjection"]; + vertexShaderIndexParam = Parameters["VertexShaderIndex"]; } } } diff --git a/Renderer.cs b/Renderer.cs index e3d2820..b5e97b7 100644 --- a/Renderer.cs +++ b/Renderer.cs @@ -220,48 +220,145 @@ namespace Kav } } - public void DepthRender( - RenderTarget2D renderTarget, + // Renders a series of drawable-transform pairs using an effect that has a World matrix. + // Effect must be pre-configured!! + public static void CullAndRenderIndexed( + GraphicsDevice graphicsDevice, PerspectiveCamera camera, - IEnumerable<(Model, Matrix)> modelTransforms - ) { - GraphicsDevice.SetRenderTarget(renderTarget); - GraphicsDevice.DepthStencilState = DepthStencilState.Default; - + IEnumerable<(T, Matrix)> drawableTransformPairs, + U effect + ) where T : IIndexDrawable, ICullable where U : Effect, IHasWorldMatrix + { var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection); - foreach (var (model, transform) in FrustumCull(boundingFrustum, modelTransforms)) + foreach (var (drawable, transform) in FrustumCull(boundingFrustum, drawableTransformPairs)) { - foreach (var modelMesh in model.Meshes) - { - foreach (var meshPart in modelMesh.MeshParts) - { - SimpleDepthEffect.World = transform; - SimpleDepthEffect.View = camera.View; - SimpleDepthEffect.Projection = camera.Projection; + effect.World = transform; - GraphicsDevice.SetVertexBuffer(meshPart.VertexBuffer); - GraphicsDevice.Indices = meshPart.IndexBuffer; - - foreach (var pass in SimpleDepthEffect.CurrentTechnique.Passes) - { - pass.Apply(); - - GraphicsDevice.DrawIndexedPrimitives( - PrimitiveType.TriangleList, - 0, - 0, - meshPart.VertexBuffer.VertexCount, - 0, - meshPart.Triangles.Length - ); - } - } - } + RenderIndexed( + graphicsDevice, + drawable, + effect + ); } } - public void SkyboxRender( + public static void RenderIndexed( + GraphicsDevice graphicsDevice, + T drawable, + U effect + ) where T : IIndexDrawable where U : Effect + { + graphicsDevice.SetVertexBuffer(drawable.VertexBuffer); + graphicsDevice.Indices = drawable.IndexBuffer; + + foreach (var pass in effect.CurrentTechnique.Passes) + { + pass.Apply(); + + graphicsDevice.DrawIndexedPrimitives( + PrimitiveType.TriangleList, + 0, + 0, + drawable.VertexBuffer.VertexCount, + 0, + drawable.IndexBuffer.IndexCount / 3 + ); + } + } + + public static int FillAndSetBuffersForInstancing( + GraphicsDevice graphicsDevice, + PerspectiveCamera camera, + T drawable, + IEnumerable transforms, + V[] vertexData, + DynamicVertexBuffer dynamicVertexBuffer + ) where T : ICullable, IIndexDrawable where V : struct, IVertexType, IHasWorldMatrix + { + var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection); + + int numInstances = 0; + foreach (var transform in FrustumCull(boundingFrustum, drawable, transforms)) + { + vertexData[numInstances].World = transform; + numInstances += 1; + } + + if (numInstances == 0) { return 0; } + + dynamicVertexBuffer.SetData( + vertexData, + 0, + numInstances, + SetDataOptions.Discard + ); + + graphicsDevice.SetVertexBuffers( + drawable.VertexBuffer, + new VertexBufferBinding(dynamicVertexBuffer, 0, 1) + ); + graphicsDevice.Indices = drawable.IndexBuffer; + + return numInstances; + } + + public static void RenderInstanced( + GraphicsDevice graphicsDevice, + T drawable, + U effect, + int numInstances + ) where T : ICullable, IIndexDrawable where U : Effect + { + foreach (var pass in effect.CurrentTechnique.Passes) + { + pass.Apply(); + + graphicsDevice.DrawInstancedPrimitives( + PrimitiveType.TriangleList, + 0, + 0, + drawable.VertexBuffer.VertexCount, + 0, + drawable.IndexBuffer.IndexCount / 3, + numInstances + ); + } + } + + // TODO: can probably make this static somehow + public void RenderFullscreenEffect( + Effect effect + ) { + foreach (var pass in effect.CurrentTechnique.Passes) + { + pass.Apply(); + GraphicsDevice.SetVertexBuffer(FullscreenTriangle); + GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1); + } + } + + public void RenderDepth( + RenderTarget2D renderTarget, + PerspectiveCamera camera, + IEnumerable<(T, Matrix)> drawableTransforms + ) where T : ICullable, IIndexDrawable + { + GraphicsDevice.SetRenderTarget(renderTarget); + GraphicsDevice.DepthStencilState = DepthStencilState.Default; + + SimpleDepthEffect.View = camera.View; + SimpleDepthEffect.Projection = camera.Projection; + + CullAndRenderIndexed( + GraphicsDevice, + camera, + drawableTransforms, + SimpleDepthEffect + ); + } + + public void RenderSkybox( RenderTarget2D renderTarget, PerspectiveCamera camera, TextureCube skybox @@ -274,41 +371,29 @@ namespace Kav var view = camera.View; view.Translation = Vector3.Zero; - SkyboxEffect.View = view; + SkyboxEffect.View = view; SkyboxEffect.Projection = camera.Projection; - GraphicsDevice.SetVertexBuffer(UnitCube.Meshes[0].MeshParts[0].VertexBuffer); - GraphicsDevice.Indices = UnitCube.Meshes[0].MeshParts[0].IndexBuffer; + RenderIndexed( + GraphicsDevice, + UnitCube.Meshes[0].MeshParts[0], + SkyboxEffect + ); - foreach (var pass in SkyboxEffect.CurrentTechnique.Passes) - { - pass.Apply(); - - GraphicsDevice.DrawIndexedPrimitives( - PrimitiveType.TriangleList, - 0, - 0, - UnitCube.Meshes[0].MeshParts[0].VertexBuffer.VertexCount, - 0, - UnitCube.Meshes[0].MeshParts[0].Triangles.Length - ); - } GraphicsDevice.RasterizerState.CullMode = CullMode.CullCounterClockwiseFace; } /// /// GBuffer binding must have 4 render targets. /// - public void InstancedGBufferRender( + public void RenderGBufferInstanced( RenderTargetBinding[] gBuffer, RenderTarget2D depthBuffer, PerspectiveCamera camera, T drawable, IEnumerable transforms ) where T : ICullable, IIndexDrawable, IGBufferDrawable { - int numInstances = 0; - GraphicsDevice.SetRenderTargets(gBuffer); GraphicsDevice.DepthStencilState = DepthStencilState.Default; GraphicsDevice.BlendState = BlendState.Opaque; @@ -326,132 +411,67 @@ namespace Kav Deferred_GBufferEffect.View = camera.View; Deferred_GBufferEffect.Projection = camera.Projection; - var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection); - - foreach (var transform in FrustumCull(boundingFrustum, drawable, transforms)) - { - GBufferInstanceVertices[numInstances].World = transform; - numInstances += 1; - } - - if (numInstances == 0) { return; } - - GBufferInstanceVertexBuffer.SetData( + var numInstances = FillAndSetBuffersForInstancing( + GraphicsDevice, + camera, + drawable, + transforms, GBufferInstanceVertices, - 0, - numInstances, - SetDataOptions.Discard + GBufferInstanceVertexBuffer ); - GraphicsDevice.SetVertexBuffers( - drawable.VertexBuffer, - new VertexBufferBinding(GBufferInstanceVertexBuffer, 0, 1) + RenderInstanced( + GraphicsDevice, + drawable, + Deferred_GBufferEffect, + numInstances ); - GraphicsDevice.Indices = drawable.IndexBuffer; - - foreach (var pass in Deferred_GBufferEffect.CurrentTechnique.Passes) - { - pass.Apply(); - GraphicsDevice.DrawInstancedPrimitives( - PrimitiveType.TriangleList, - 0, - 0, - drawable.VertexBuffer.VertexCount, - 0, - drawable.IndexBuffer.IndexCount / 3, - numInstances - ); - } + // re-render to get depth GraphicsDevice.SetRenderTarget(depthBuffer); - foreach (var pass in Deferred_GBufferEffect.CurrentTechnique.Passes) - { - pass.Apply(); - GraphicsDevice.DrawInstancedPrimitives( - PrimitiveType.TriangleList, - 0, - 0, - drawable.VertexBuffer.VertexCount, - 0, - drawable.IndexBuffer.IndexCount / 3, - numInstances - ); - } - - //SimpleDepthEffect.HardwareInstancingEnabled = true; - //SimpleDepthEffect.View = camera.View; - //SimpleDepthEffect.Projection = camera.Projection; - - //foreach (var pass in SimpleDepthEffect.CurrentTechnique.Passes) - //{ - // pass.Apply(); - - // GraphicsDevice.DrawInstancedPrimitives( - // PrimitiveType.TriangleList, - // 0, - // 0, - // drawable.VertexBuffer.VertexCount, - // 0, - // drawable.IndexBuffer.IndexCount / 3, - // numInstances - // ); - //} + RenderInstanced( + GraphicsDevice, + drawable, + Deferred_GBufferEffect, + numInstances + ); } - public void GBufferRender( + public void RenderGBufferIndexed( RenderTargetBinding[] gBuffer, PerspectiveCamera camera, - IEnumerable<(Model, Matrix)> modelTransforms - ) { + IEnumerable<(T, Matrix)> drawableTransforms + ) where T : ICullable, IIndexDrawable, IGBufferDrawable { GraphicsDevice.SetRenderTargets(gBuffer); GraphicsDevice.DepthStencilState = DepthStencilState.Default; GraphicsDevice.BlendState = BlendState.Opaque; + Deferred_GBufferEffect.HardwareInstancingEnabled = false; + Deferred_GBufferEffect.View = camera.View; + Deferred_GBufferEffect.Projection = camera.Projection; + var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection); - foreach (var (model, transform) in FrustumCull(boundingFrustum, modelTransforms)) + foreach (var (drawable, transform) in FrustumCull(boundingFrustum, drawableTransforms)) { - foreach (var modelMesh in model.Meshes) - { - foreach (var meshPart in modelMesh.MeshParts) - { - Deferred_GBufferEffect.World = transform; - Deferred_GBufferEffect.View = camera.View; - Deferred_GBufferEffect.Projection = camera.Projection; + Deferred_GBufferEffect.World = transform; - Deferred_GBufferEffect.HardwareInstancingEnabled = false; + Deferred_GBufferEffect.HardwareInstancingEnabled = false; - Deferred_GBufferEffect.Albedo = meshPart.Albedo; - Deferred_GBufferEffect.Metallic = meshPart.Metallic; - Deferred_GBufferEffect.Roughness = meshPart.Roughness; + Deferred_GBufferEffect.Albedo = drawable.Albedo; + Deferred_GBufferEffect.Metallic = drawable.Metallic; + Deferred_GBufferEffect.Roughness = drawable.Roughness; - Deferred_GBufferEffect.AlbedoTexture = meshPart.AlbedoTexture; - Deferred_GBufferEffect.NormalTexture = meshPart.NormalTexture; - Deferred_GBufferEffect.MetallicRoughnessTexture = meshPart.MetallicRoughnessTexture; + Deferred_GBufferEffect.AlbedoTexture = drawable.AlbedoTexture; + Deferred_GBufferEffect.NormalTexture = drawable.NormalTexture; + Deferred_GBufferEffect.MetallicRoughnessTexture = drawable.MetallicRoughnessTexture; - GraphicsDevice.SetVertexBuffer(meshPart.VertexBuffer); - GraphicsDevice.Indices = meshPart.IndexBuffer; - - foreach (var pass in Deferred_GBufferEffect.CurrentTechnique.Passes) - { - pass.Apply(); - - GraphicsDevice.DrawIndexedPrimitives( - PrimitiveType.TriangleList, - 0, - 0, - meshPart.VertexBuffer.VertexCount, - 0, - meshPart.Triangles.Length - ); - } - } - } + RenderIndexed(GraphicsDevice, drawable, Deferred_GBufferEffect); } } - public void AmbientLightRender( + public void RenderAmbientLight( RenderTarget2D renderTarget, Texture2D gPosition, Texture2D gAlbedo, @@ -465,25 +485,20 @@ namespace Kav DeferredAmbientLightEffect.GAlbedo = gAlbedo; DeferredAmbientLightEffect.AmbientColor = ambientLight.Color.ToVector3(); - foreach (var pass in DeferredAmbientLightEffect.CurrentTechnique.Passes) - { - pass.Apply(); - GraphicsDevice.SetVertexBuffer(FullscreenTriangle); - GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1); - } + RenderFullscreenEffect(DeferredAmbientLightEffect); } - public void PointLightRender( + public void RenderPointLight( RenderTarget2D renderTarget, Texture2D gPosition, Texture2D gAlbedo, Texture2D gNormal, Texture2D gMetallicRoughness, PerspectiveCamera camera, - IEnumerable<(Model, Matrix)> modelTransforms, + IEnumerable<(T, Matrix)> modelTransforms, PointLight pointLight - ) { - RenderPointShadows(camera, modelTransforms, pointLight); + ) where T : ICullable, IIndexDrawable { + RenderPointShadows(PointShadowCubeMap, camera, modelTransforms, pointLight); GraphicsDevice.SetRenderTarget(renderTarget); GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead; @@ -503,26 +518,21 @@ namespace Kav DeferredPointLightEffect.FarPlane = 25f; // FIXME: magic value - foreach (var pass in DeferredPointLightEffect.CurrentTechnique.Passes) - { - pass.Apply(); - GraphicsDevice.SetVertexBuffer(FullscreenTriangle); - GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1); - } + RenderFullscreenEffect(DeferredPointLightEffect); } - public void DirectionalLightRender( + public void RenderDirectionalLight( RenderTarget2D renderTarget, Texture2D gPosition, Texture2D gAlbedo, Texture2D gNormal, Texture2D gMetallicRoughness, PerspectiveCamera camera, - IEnumerable<(Model, Matrix)> modelTransforms, + IEnumerable<(T, Matrix)> modelTransforms, DirectionalLight directionalLight, int numShadowCascades - ) { - RenderDirectionalShadows(camera, modelTransforms, directionalLight, DeferredDirectionalLightEffect); + ) where T : ICullable, IIndexDrawable { + //RenderDirectionalShadows(camera, modelTransforms, directionalLight, DeferredDirectionalLightEffect); GraphicsDevice.SetRenderTarget(renderTarget); GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead; @@ -554,27 +564,22 @@ namespace Kav DeferredDirectionalLightEffect.ViewMatrix = camera.View; DeferredDirectionalLightEffect.EyePosition = camera.Position; - foreach (EffectPass pass in DeferredDirectionalLightEffect.CurrentTechnique.Passes) - { - pass.Apply(); - GraphicsDevice.SetVertexBuffer(FullscreenTriangle); - GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1); - } + RenderFullscreenEffect(DeferredDirectionalLightEffect); } - public void DirectionalLightToonRender( + public void RenderDirectionalLightToon( RenderTarget2D renderTarget, Texture2D gPosition, Texture2D gAlbedo, Texture2D gNormal, Texture2D gMetallicRoughness, PerspectiveCamera camera, - IEnumerable<(Model, Matrix)> modelTransforms, + IEnumerable<(T, Matrix)> modelTransforms, DirectionalLight directionalLight, int numShadowCascades, bool ditheredShadows - ) { - RenderDirectionalShadows(camera, modelTransforms, directionalLight, Deferred_ToonEffect); + ) where T : ICullable, IIndexDrawable { + //RenderDirectionalShadows(camera, modelTransforms, directionalLight, Deferred_ToonEffect); GraphicsDevice.SetRenderTarget(renderTarget); GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead; @@ -609,20 +614,15 @@ namespace Kav Deferred_ToonEffect.ViewMatrix = camera.View; - foreach (EffectPass pass in Deferred_ToonEffect.CurrentTechnique.Passes) - { - pass.Apply(); - GraphicsDevice.SetVertexBuffer(FullscreenTriangle); - GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1); - } + RenderFullscreenEffect(Deferred_ToonEffect); } - private void RenderDirectionalShadows( + private void RenderDirectionalShadows( PerspectiveCamera camera, IEnumerable<(Model, Matrix)> modelTransforms, DirectionalLight directionalLight, ShadowCascadeEffect effect - ) { + ) where T : ICullable, IIndexDrawable { // render the individual shadow cascades var previousFarPlane = camera.NearPlane; for (var i = 0; i < NumShadowCascades; i++) @@ -739,26 +739,18 @@ namespace Kav } } - private void RenderPointShadows( + private void RenderPointShadows( + RenderTargetCube pointShadowCubeMap, PerspectiveCamera camera, - IEnumerable<(Model, Matrix)> modelTransforms, + IEnumerable<(T, Matrix)> modelTransforms, PointLight pointLight - ) { + ) where T : ICullable, IIndexDrawable { GraphicsDevice.DepthStencilState = DepthStencilState.Default; GraphicsDevice.BlendState = BlendState.Opaque; - LinearDepthEffect.Projection = Matrix.CreatePerspectiveFieldOfView( - MathHelper.PiOver2, - 1, - 0.1f, - 25f // FIXME: magic value - ); - LinearDepthEffect.FarPlane = 25f; - LinearDepthEffect.LightPosition = pointLight.Position; - foreach (CubeMapFace face in Enum.GetValues(typeof(CubeMapFace))) { - GraphicsDevice.SetRenderTarget(PointShadowCubeMap, face); + GraphicsDevice.SetRenderTarget(pointShadowCubeMap, face); Vector3 targetDirection; Vector3 targetUpDirection; @@ -805,36 +797,22 @@ namespace Kav pointLight.Position + targetDirection, targetUpDirection ); + LinearDepthEffect.Projection = Matrix.CreatePerspectiveFieldOfView( + MathHelper.PiOver2, + 1, + 0.1f, + 25f // FIXME: magic value + ); + LinearDepthEffect.FarPlane = 25f; - var boundingFrustum = new BoundingFrustum(LinearDepthEffect.View * LinearDepthEffect.Projection); + LinearDepthEffect.LightPosition = pointLight.Position; - foreach (var (model, transform) in FrustumCull(boundingFrustum, modelTransforms)) - { - foreach (var modelMesh in model.Meshes) - { - foreach (var meshPart in modelMesh.MeshParts) - { - GraphicsDevice.SetVertexBuffer(meshPart.VertexBuffer); - GraphicsDevice.Indices = meshPart.IndexBuffer; - - LinearDepthEffect.Model = transform; - - foreach (var pass in LinearDepthEffect.CurrentTechnique.Passes) - { - pass.Apply(); - - GraphicsDevice.DrawIndexedPrimitives( - PrimitiveType.TriangleList, - 0, - 0, - meshPart.VertexBuffer.VertexCount, - 0, - meshPart.Triangles.Length - ); - } - } - } - } + CullAndRenderIndexed( + GraphicsDevice, + camera, + modelTransforms, + LinearDepthEffect + ); } } diff --git a/Vertices/GBufferInstanceVertex.cs b/Vertices/GBufferInstanceVertex.cs index 329c8e9..32ae321 100644 --- a/Vertices/GBufferInstanceVertex.cs +++ b/Vertices/GBufferInstanceVertex.cs @@ -5,7 +5,7 @@ using Microsoft.Xna.Framework.Graphics; namespace Kav { [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct GBufferInstanceVertex : IVertexType + public struct GBufferInstanceVertex : IVertexType, IHasWorldMatrix { VertexDeclaration IVertexType.VertexDeclaration {