Batched Billboard Implementation #5
			
				
			
		
		
		
	|  | @ -0,0 +1,39 @@ | ||||||
|  | using Microsoft.Xna.Framework; | ||||||
|  | using Microsoft.Xna.Framework.Graphics; | ||||||
|  | 
 | ||||||
|  | namespace Kav | ||||||
|  | { | ||||||
|  |     public struct Sprite | ||||||
|  |     { | ||||||
|  |         public Texture2D Texture { get; } | ||||||
|  |         public Vector3 Position { get; } | ||||||
|  |         public Vector2 Origin { get; } | ||||||
|  |         public float Rotation { get; } | ||||||
|  |         public Vector2 Scale { get; } | ||||||
|  | 
 | ||||||
|  |         public Sprite( | ||||||
|  |             Texture2D texture, | ||||||
|  |             Vector3 position, | ||||||
|  |             Vector2 origin, | ||||||
|  |             float rotation, | ||||||
|  |             Vector2 scale | ||||||
|  |         ) { | ||||||
|  |             Texture = texture; | ||||||
|  |             Position = position; | ||||||
|  |             Origin = origin; | ||||||
|  |             Rotation = rotation; | ||||||
|  |             Scale = scale; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public Sprite( | ||||||
|  |             Texture2D texture, | ||||||
|  |             Vector3 position | ||||||
|  |         ) { | ||||||
|  |             Texture = texture; | ||||||
|  |             Position = position; | ||||||
|  |             Origin = Vector2.Zero; | ||||||
|  |             Rotation = 0f; | ||||||
|  |             Scale = Vector2.One; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										91
									
								
								Renderer.cs
								
								
								
								
							
							
						
						
									
										91
									
								
								Renderer.cs
								
								
								
								
							|  | @ -33,6 +33,7 @@ namespace Kav | ||||||
|         private LinearDepthEffect LinearDepthEffect { get; } |         private LinearDepthEffect LinearDepthEffect { get; } | ||||||
|         private Effect ToneMapEffect { get; } |         private Effect ToneMapEffect { get; } | ||||||
|         private SkyboxEffect SkyboxEffect { get; } |         private SkyboxEffect SkyboxEffect { get; } | ||||||
|  |         private BasicEffect BasicEffect { get; } | ||||||
| 
 | 
 | ||||||
|         private RenderTarget2D gPosition { get; } |         private RenderTarget2D gPosition { get; } | ||||||
|         private RenderTarget2D gNormal { get; } |         private RenderTarget2D gNormal { get; } | ||||||
|  | @ -159,6 +160,7 @@ namespace Kav | ||||||
|             ToneMapEffect = new Effect(graphicsDevice, Resources.ToneMapEffect); |             ToneMapEffect = new Effect(graphicsDevice, Resources.ToneMapEffect); | ||||||
|             Deferred_ToonEffect = new Deferred_ToonEffect(GraphicsDevice); |             Deferred_ToonEffect = new Deferred_ToonEffect(GraphicsDevice); | ||||||
|             SkyboxEffect = new SkyboxEffect(GraphicsDevice); |             SkyboxEffect = new SkyboxEffect(GraphicsDevice); | ||||||
|  |             BasicEffect = new BasicEffect(GraphicsDevice); | ||||||
| 
 | 
 | ||||||
|             FullscreenTriangle = new VertexBuffer(GraphicsDevice, typeof(VertexPositionTexture), 3, BufferUsage.WriteOnly); |             FullscreenTriangle = new VertexBuffer(GraphicsDevice, typeof(VertexPositionTexture), 3, BufferUsage.WriteOnly); | ||||||
|             FullscreenTriangle.SetData(new VertexPositionTexture[3] { |             FullscreenTriangle.SetData(new VertexPositionTexture[3] { | ||||||
|  | @ -176,6 +178,7 @@ namespace Kav | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public void DeferredRender( |         public void DeferredRender( | ||||||
|  |             RenderTarget2D renderTarget, | ||||||
|             PerspectiveCamera camera, |             PerspectiveCamera camera, | ||||||
|             IEnumerable<(Model, Matrix)> modelTransforms, |             IEnumerable<(Model, Matrix)> modelTransforms, | ||||||
|             AmbientLight ambientLight, |             AmbientLight ambientLight, | ||||||
|  | @ -198,21 +201,21 @@ namespace Kav | ||||||
| 
 | 
 | ||||||
|             DirectionalLightRender(camera, modelTransforms, directionalLight); |             DirectionalLightRender(camera, modelTransforms, directionalLight); | ||||||
| 
 | 
 | ||||||
|             GraphicsDevice.SetRenderTarget(null); |             GraphicsDevice.SetRenderTarget(renderTarget); | ||||||
|             GraphicsDevice.Clear(Color.Black); |  | ||||||
|             SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, null, null, null, ToneMapEffect); |             SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, null, null, null, ToneMapEffect); | ||||||
|             SpriteBatch.Draw(ColorRenderTarget, Vector2.Zero, Color.White); |             SpriteBatch.Draw(ColorRenderTarget, Vector2.Zero, Color.White); | ||||||
|             SpriteBatch.End(); |             SpriteBatch.End(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public void DeferredToonRender( |         public void DeferredToonRender( | ||||||
|  |             RenderTarget2D renderTarget, | ||||||
|             PerspectiveCamera camera, |             PerspectiveCamera camera, | ||||||
|             IEnumerable<(Model, Matrix)> modelTransforms, |             IEnumerable<(Model, Matrix)> modelTransforms, | ||||||
|             AmbientLight ambientLight, |             AmbientLight ambientLight, | ||||||
|             IEnumerable<PointLight> pointLights, |             IEnumerable<PointLight> pointLights, | ||||||
|             DirectionalLight directionalLight, |             DirectionalLight directionalLight, | ||||||
|             TextureCube skybox |             TextureCube skybox | ||||||
|         ) {             |         ) { | ||||||
|             GBufferRender(camera, modelTransforms); |             GBufferRender(camera, modelTransforms); | ||||||
| 
 | 
 | ||||||
|             GraphicsDevice.SetRenderTarget(ColorRenderTarget); |             GraphicsDevice.SetRenderTarget(ColorRenderTarget); | ||||||
|  | @ -230,12 +233,64 @@ namespace Kav | ||||||
|             DirectionalLightToonRender(camera, modelTransforms, directionalLight); |             DirectionalLightToonRender(camera, modelTransforms, directionalLight); | ||||||
|             SkyboxRender(camera, skybox); |             SkyboxRender(camera, skybox); | ||||||
| 
 | 
 | ||||||
|             GraphicsDevice.SetRenderTarget(null); |             GraphicsDevice.SetRenderTarget(renderTarget); | ||||||
|             SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, null, null, null, null); |             SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, null, null, null, null); | ||||||
|             SpriteBatch.Draw(ColorRenderTarget, Vector2.Zero, Color.White); |             SpriteBatch.Draw(ColorRenderTarget, Vector2.Zero, Color.White); | ||||||
|             SpriteBatch.End(); |             SpriteBatch.End(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         // billboards sprites into the scene | ||||||
|  |         // FIXME: we can frustum cull the sprites probably | ||||||
|  |         public void BillboardSpriteRender( | ||||||
|  |             RenderTarget2D renderTarget, | ||||||
|  |             PerspectiveCamera camera, | ||||||
|  |             IEnumerable<(Model, Matrix)> modelTransforms, | ||||||
|  |             IEnumerable<Sprite> sprites | ||||||
|  |         ) { | ||||||
|  |             GraphicsDevice.SetRenderTarget(ColorRenderTarget); | ||||||
|  |             GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1f, 0); | ||||||
|  |             GraphicsDevice.DepthStencilState = DepthStencilState.Default; | ||||||
|  | 
 | ||||||
|  |             DepthRender(camera, modelTransforms); | ||||||
|  |             GraphicsDevice.Clear(ClearOptions.Target, new Color(0, 0, 0, 0), 1f, 0); | ||||||
|  | 
 | ||||||
|  |             Matrix invertY = Matrix.CreateScale(1, -1, 1); | ||||||
|  | 
 | ||||||
|  |             BasicEffect.World = invertY; | ||||||
|  |             BasicEffect.View = Matrix.Identity; | ||||||
|  |             BasicEffect.Projection = camera.Projection; | ||||||
|  |             BasicEffect.TextureEnabled = true; | ||||||
|  |             BasicEffect.VertexColorEnabled = true; | ||||||
|  | 
 | ||||||
|  |             SpriteBatch.Begin(0, null, null, DepthStencilState.DepthRead, RasterizerState.CullNone, BasicEffect); | ||||||
|  | 
 | ||||||
|  |             foreach (var sprite in sprites) | ||||||
|  |             { | ||||||
|  |                 // transform view space on CPU so we don't have to break the batch | ||||||
|  |                 Vector3 viewSpacePosition = Vector3.Transform(sprite.Position, camera.View * invertY); | ||||||
|  | 
 | ||||||
|  |                 SpriteBatch.Draw( | ||||||
|  |                     sprite.Texture, | ||||||
|  |                     new Vector2(viewSpacePosition.X, viewSpacePosition.Y), | ||||||
|  |                     null, | ||||||
|  |                     Color.White, | ||||||
|  |                     0, | ||||||
|  |                     sprite.Origin, | ||||||
|  |                     sprite.Scale / new Vector2(sprite.Texture.Width, sprite.Texture.Height), | ||||||
|  |                     0, | ||||||
|  |                     viewSpacePosition.Z | ||||||
|  |                 ); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             SpriteBatch.End(); | ||||||
|  | 
 | ||||||
|  |             GraphicsDevice.SetRenderTarget(renderTarget); | ||||||
|  |             GraphicsDevice.Clear(new Color(0, 0, 0, 0)); | ||||||
|  |             SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, null, null, null); | ||||||
|  |             SpriteBatch.Draw(ColorRenderTarget, Vector2.Zero, Color.White); | ||||||
|  |             SpriteBatch.End(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         private void DepthRender( |         private void DepthRender( | ||||||
|             PerspectiveCamera camera, |             PerspectiveCamera camera, | ||||||
|             IEnumerable<(Model, Matrix)> modelTransforms |             IEnumerable<(Model, Matrix)> modelTransforms | ||||||
|  | @ -386,11 +441,11 @@ namespace Kav | ||||||
|             DeferredPointLightEffect.GPosition = gPosition; |             DeferredPointLightEffect.GPosition = gPosition; | ||||||
|             DeferredPointLightEffect.GAlbedo = gAlbedo; |             DeferredPointLightEffect.GAlbedo = gAlbedo; | ||||||
|             DeferredPointLightEffect.GNormal = gNormal; |             DeferredPointLightEffect.GNormal = gNormal; | ||||||
|             DeferredPointLightEffect.GMetallicRoughness = gMetallicRoughness;     |             DeferredPointLightEffect.GMetallicRoughness = gMetallicRoughness; | ||||||
|             DeferredPointLightEffect.ShadowMap = PointShadowCubeMap; |             DeferredPointLightEffect.ShadowMap = PointShadowCubeMap; | ||||||
| 
 | 
 | ||||||
|             DeferredPointLightEffect.PointLightPosition = pointLight.Position; |             DeferredPointLightEffect.PointLightPosition = pointLight.Position; | ||||||
|             DeferredPointLightEffect.PointLightColor =  |             DeferredPointLightEffect.PointLightColor = | ||||||
|                 pointLight.Color.ToVector3() * pointLight.Intensity; |                 pointLight.Color.ToVector3() * pointLight.Intensity; | ||||||
| 
 | 
 | ||||||
|             DeferredPointLightEffect.FarPlane = 25f; // FIXME: magic value |             DeferredPointLightEffect.FarPlane = 25f; // FIXME: magic value | ||||||
|  | @ -428,11 +483,11 @@ namespace Kav | ||||||
|             { |             { | ||||||
|                 DeferredDirectionalLightEffect.ShadowMapFour = ShadowRenderTargets[3]; |                 DeferredDirectionalLightEffect.ShadowMapFour = ShadowRenderTargets[3]; | ||||||
|             } |             } | ||||||
|              | 
 | ||||||
|             DeferredDirectionalLightEffect.DirectionalLightDirection = directionalLight.Direction; |             DeferredDirectionalLightEffect.DirectionalLightDirection = directionalLight.Direction; | ||||||
|             DeferredDirectionalLightEffect.DirectionalLightColor =  |             DeferredDirectionalLightEffect.DirectionalLightColor = | ||||||
|                 directionalLight.Color.ToVector3() * directionalLight.Intensity; |                 directionalLight.Color.ToVector3() * directionalLight.Intensity; | ||||||
|              | 
 | ||||||
|             DeferredDirectionalLightEffect.ViewMatrix = camera.View; |             DeferredDirectionalLightEffect.ViewMatrix = camera.View; | ||||||
|             DeferredDirectionalLightEffect.EyePosition = camera.Position; |             DeferredDirectionalLightEffect.EyePosition = camera.Position; | ||||||
| 
 | 
 | ||||||
|  | @ -467,7 +522,7 @@ namespace Kav | ||||||
| 
 | 
 | ||||||
|             Deferred_ToonEffect.EyePosition = camera.Position; |             Deferred_ToonEffect.EyePosition = camera.Position; | ||||||
|             Deferred_ToonEffect.DirectionalLightDirection = directionalLight.Direction; |             Deferred_ToonEffect.DirectionalLightDirection = directionalLight.Direction; | ||||||
|             Deferred_ToonEffect.DirectionalLightColor =  |             Deferred_ToonEffect.DirectionalLightColor = | ||||||
|                 directionalLight.Color.ToVector3() * directionalLight.Intensity; |                 directionalLight.Color.ToVector3() * directionalLight.Intensity; | ||||||
| 
 | 
 | ||||||
|             Deferred_ToonEffect.ShadowMapOne = ShadowRenderTargets[0]; |             Deferred_ToonEffect.ShadowMapOne = ShadowRenderTargets[0]; | ||||||
|  | @ -483,7 +538,7 @@ namespace Kav | ||||||
|             { |             { | ||||||
|                 Deferred_ToonEffect.ShadowMapFour = ShadowRenderTargets[3]; |                 Deferred_ToonEffect.ShadowMapFour = ShadowRenderTargets[3]; | ||||||
|             } |             } | ||||||
|              | 
 | ||||||
|             Deferred_ToonEffect.ViewMatrix = camera.View; |             Deferred_ToonEffect.ViewMatrix = camera.View; | ||||||
| 
 | 
 | ||||||
|             foreach (EffectPass pass in Deferred_ToonEffect.CurrentTechnique.Passes) |             foreach (EffectPass pass in Deferred_ToonEffect.CurrentTechnique.Passes) | ||||||
|  | @ -506,7 +561,7 @@ namespace Kav | ||||||
|             { |             { | ||||||
|                 var farPlane = camera.FarPlane / (MathHelper.Max((NumShadowCascades - i - 1) * 2f, 1f)); |                 var farPlane = camera.FarPlane / (MathHelper.Max((NumShadowCascades - i - 1) * 2f, 1f)); | ||||||
| 
 | 
 | ||||||
|                 // divide the view frustum  |                 // divide the view frustum | ||||||
|                 var shadowCamera = new PerspectiveCamera( |                 var shadowCamera = new PerspectiveCamera( | ||||||
|                     camera.Position, |                     camera.Position, | ||||||
|                     camera.Forward, |                     camera.Forward, | ||||||
|  | @ -516,7 +571,7 @@ namespace Kav | ||||||
|                     previousFarPlane, |                     previousFarPlane, | ||||||
|                     farPlane |                     farPlane | ||||||
|                 ); |                 ); | ||||||
|                  | 
 | ||||||
|                 // TODO: This is tightly coupled to the effect and it sucks |                 // TODO: This is tightly coupled to the effect and it sucks | ||||||
|                 RenderDirectionalShadowMap(shadowCamera, modelTransforms, directionalLight, effect, i); |                 RenderDirectionalShadowMap(shadowCamera, modelTransforms, directionalLight, effect, i); | ||||||
| 
 | 
 | ||||||
|  | @ -526,8 +581,8 @@ namespace Kav | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private void RenderDirectionalShadowMap( |         private void RenderDirectionalShadowMap( | ||||||
|             PerspectiveCamera camera,  |             PerspectiveCamera camera, | ||||||
|             IEnumerable<(Model, Matrix)> modelTransforms,  |             IEnumerable<(Model, Matrix)> modelTransforms, | ||||||
|             DirectionalLight directionalLight, |             DirectionalLight directionalLight, | ||||||
|             ShadowCascadeEffect effect, |             ShadowCascadeEffect effect, | ||||||
|             int shadowCascadeIndex |             int shadowCascadeIndex | ||||||
|  | @ -536,7 +591,7 @@ namespace Kav | ||||||
|             GraphicsDevice.Clear(Color.White); |             GraphicsDevice.Clear(Color.White); | ||||||
|             GraphicsDevice.DepthStencilState = DepthStencilState.Default; |             GraphicsDevice.DepthStencilState = DepthStencilState.Default; | ||||||
|             GraphicsDevice.BlendState = BlendState.Opaque; |             GraphicsDevice.BlendState = BlendState.Opaque; | ||||||
|              | 
 | ||||||
|             var cameraBoundingFrustum = new BoundingFrustum(camera.View * camera.Projection); |             var cameraBoundingFrustum = new BoundingFrustum(camera.View * camera.Projection); | ||||||
|             Vector3[] frustumCorners = cameraBoundingFrustum.GetCorners(); |             Vector3[] frustumCorners = cameraBoundingFrustum.GetCorners(); | ||||||
| 
 | 
 | ||||||
|  | @ -555,7 +610,7 @@ namespace Kav | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             BoundingBox lightBox = BoundingBox.CreateFromPoints(frustumCorners); |             BoundingBox lightBox = BoundingBox.CreateFromPoints(frustumCorners); | ||||||
|              | 
 | ||||||
|             SimpleDepthEffect.View = lightView; |             SimpleDepthEffect.View = lightView; | ||||||
|             SimpleDepthEffect.Projection = Matrix.CreateOrthographicOffCenter( |             SimpleDepthEffect.Projection = Matrix.CreateOrthographicOffCenter( | ||||||
|                 lightBox.Min.X, |                 lightBox.Min.X, | ||||||
|  | @ -586,7 +641,7 @@ namespace Kav | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             var boundingFrustum = new BoundingFrustum(lightSpaceMatrix); |             var boundingFrustum = new BoundingFrustum(lightSpaceMatrix); | ||||||
|              | 
 | ||||||
|             foreach (var (model, transform) in FrustumCull(boundingFrustum, modelTransforms)) |             foreach (var (model, transform) in FrustumCull(boundingFrustum, modelTransforms)) | ||||||
|             { |             { | ||||||
|                 foreach (var modelMesh in model.Meshes) |                 foreach (var modelMesh in model.Meshes) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue