batched billboard implementation
							parent
							
								
									d83aacd57f
								
							
						
					
					
						commit
						acaafdcdcd
					
				| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										87
									
								
								Renderer.cs
								
								
								
								
							
							
						
						
									
										87
									
								
								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] {
 | 
				
			||||||
| 
						 | 
					@ -206,13 +208,14 @@ namespace Kav
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        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 * Matrix.CreateRotationX(sprite.Rotation) * 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