Beispiel #1
0
        public void Render(
            GraphicsDevice graphics,
            Shader effect,
            Camera cam,
            string mode)
        {
            effect.EnableWind = EnableWind;
            Camera            = cam;

            if (HardwareInstancingSupported && (instanceBuffer == null || instanceBuffer.IsContentLost || instanceBuffer.IsDisposed))
            {
                instanceBuffer = new DynamicVertexBuffer(graphics, InstancedVertex.VertexDeclaration, numInstances,
                                                         BufferUsage.None);
            }

            if (SortedData.Data.Count > 0 && numActiveInstances > 0)
            {
                graphics.RasterizerState = rasterState;

                effect.CurrentTechnique = effect.Techniques[mode];
                effect.EnableLighting   = true;
                effect.VertexColorTint  = Color.White;

                if (Texture == null || Texture.GraphicsDevice.IsDisposed)
                {
                    Texture = AssetManager.GetContentTexture(TextureAsset);
                }

                if (Model.VertexBuffer == null || Model.IndexBuffer == null || Model.VertexBuffer.IsDisposed || Model.VertexBuffer.IsContentLost)
                {
                    Model.ResetBuffer(graphics);
                    Model.Texture = new NamedImageFrame(TextureAsset);
                }

                bool hasIndex = Model.IndexBuffer != null;
                graphics.Indices = Model.IndexBuffer;

                BlendState blendState = graphics.BlendState;
                graphics.BlendState = BlendMode;

                effect.MainTexture = Texture;
                effect.LightRamp   = Color.White;

                if (HardwareInstancingSupported)
                {
                    instanceBuffer.SetData(instanceVertexes, 0, SortedData.Data.Count, SetDataOptions.Discard);

                    graphics.SetVertexBuffers(Model.VertexBuffer, new VertexBufferBinding(instanceBuffer, 0, 1));

                    try
                    {
                        DrawInstanced(graphics, effect, cam);
                    }
                    catch (NoSuitableGraphicsDeviceException exception)
                    {
                        System.Console.WriteLine(exception.ToString());
                        HardwareInstancingSupported = false;
                    }
                }
                else
                {
                    // Fallback case when hardware instancing is not supported
                    effect.SetTexturedTechnique();
                    DrawNonInstanced(graphics, effect, cam);
                }

                effect.SetTexturedTechnique();
                effect.World        = Matrix.Identity;
                graphics.BlendState = blendState;
            }
            effect.EnableWind = false;
        }
        private void Flush(
            InstanceGroup Group,
            GraphicsDevice Device,
            Shader Effect,
            Camera Camera,
            RenderMode Mode)
        {
            if (InstanceBuffer == null)
            {
                InstanceBuffer = new DynamicVertexBuffer(Device, InstancedVertex.VertexDeclaration, InstanceQueueSize, BufferUsage.None);
            }

            Effect.EnableWind      = Group.RenderData.EnableWind;
            Device.RasterizerState = new RasterizerState {
                CullMode = CullMode.None
            };
            if (Mode == RenderMode.Normal)
            {
                Effect.SetInstancedTechnique();
            }
            else
            {
                Effect.CurrentTechnique = Effect.Techniques[Shader.Technique.SelectionBufferInstanced];
            }
            Effect.EnableLighting  = true;
            Effect.VertexColorTint = Color.White;

            if (Group.RenderData.Model.VertexBuffer == null || Group.RenderData.Model.IndexBuffer == null)
            {
                Group.RenderData.Model.ResetBuffer(Device);
            }

            bool hasIndex = Group.RenderData.Model.IndexBuffer != null;

            Device.Indices = Group.RenderData.Model.IndexBuffer;

            BlendState blendState = Device.BlendState;

            Device.BlendState = Mode == RenderMode.Normal ? Group.RenderData.BlendMode : BlendState.Opaque;

            Effect.MainTexture   = Group.RenderData.Model.Texture;
            Effect.LightRampTint = Color.White;

            InstanceBuffer.SetData(Group.Instances, 0, Group.InstanceCount, SetDataOptions.Discard);
            Device.SetVertexBuffers(Group.RenderData.Model.VertexBuffer, new VertexBufferBinding(
                                        InstanceBuffer, 0, 1));

            foreach (EffectPass pass in Effect.CurrentTechnique.Passes)
            {
                pass.Apply();
                Device.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0,
                                               Group.RenderData.Model.VertexCount, 0,
                                               Group.RenderData.Model.Indexes.Length / 3,
                                               Group.InstanceCount);
            }


            Effect.SetTexturedTechnique();
            Effect.World      = Matrix.Identity;
            Device.BlendState = blendState;
            Effect.EnableWind = false;

            Group.InstanceCount = 0;
        }
        /// <summary>
        /// Called when a frame is to be drawn to the screen
        /// </summary>
        /// <param name="gameTime">The current time</param>
        public void Render(DwarfTime gameTime)
        {
            if (!World.ShowingWorld)
            {
                return;
            }
            ValidateShader();
            var frustum     = Camera.GetDrawFrustum();
            var renderables = World.EnumerateIntersectingObjects(frustum,
                                                                 r => (Debugger.Switches.DrawInvisible || r.IsVisible) && !World.ChunkManager.IsAboveCullPlane(r.GetBoundingBox()));

            // Controls the sky fog
            float x = (1.0f - Sky.TimeOfDay);

            x = x * x;
            DefaultShader.FogColor       = new Color(0.32f * x, 0.58f * x, 0.9f * x);
            DefaultShader.LightPositions = LightPositions;

            CompositeLibrary.Render(GraphicsDevice);
            CompositeLibrary.Update();

            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            GraphicsDevice.BlendState        = BlendState.Opaque;

            if (lastWaterHeight < 0) // Todo: Seriously, every single frame??
            {
                lastWaterHeight = 0;
                foreach (var chunk in World.ChunkManager.ChunkMap)
                {
                    for (int y = 0; y < VoxelConstants.ChunkSizeY; y++)
                    {
                        if (chunk.Data.LiquidPresent[y] > 0)
                        {
                            lastWaterHeight = Math.Max(y + chunk.Origin.Y, lastWaterHeight);
                        }
                    }
                }
            }

            // Computes the water height.
            float wHeight = WaterRenderer.GetVisibleWaterHeight(World.ChunkManager, Camera, GraphicsDevice.Viewport,
                                                                lastWaterHeight);

            lastWaterHeight = wHeight;

            // Draw reflection/refraction images
            WaterRenderer.DrawReflectionMap(renderables, gameTime, World, wHeight - 0.1f,
                                            GetReflectedCameraMatrix(wHeight),
                                            DefaultShader, GraphicsDevice);


            #region Draw Selection Buffer.

            if (SelectionBuffer == null)
            {
                SelectionBuffer = new SelectionBuffer(8, GraphicsDevice);
            }

            GraphicsDevice.RasterizerState   = RasterizerState.CullNone;
            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            GraphicsDevice.BlendState        = BlendState.Opaque;

            // Defines the current slice for the GPU
            var   level      = PersistentSettings.MaxViewingLevel >= World.WorldSizeInVoxels.Y ? 1000.0f : PersistentSettings.MaxViewingLevel + 0.25f;
            Plane slicePlane = WaterRenderer.CreatePlane(level, new Vector3(0, -1, 0), Camera.ViewMatrix, false);

            if (SelectionBuffer.Begin(GraphicsDevice))
            {
                // Draw the whole world, and make sure to handle slicing
                DefaultShader.ClipPlane       = new Vector4(slicePlane.Normal, slicePlane.D);
                DefaultShader.ClippingEnabled = true;
                DefaultShader.View            = Camera.ViewMatrix;
                DefaultShader.Projection      = Camera.ProjectionMatrix;
                DefaultShader.World           = Matrix.Identity;

                //GamePerformance.Instance.StartTrackPerformance("Render - Selection Buffer - Chunks");
                ChunkRenderer.RenderSelectionBuffer(DefaultShader, GraphicsDevice, Camera.ViewMatrix);
                //GamePerformance.Instance.StopTrackPerformance("Render - Selection Buffer - Chunks");

                //GamePerformance.Instance.StartTrackPerformance("Render - Selection Buffer - Components");
                ComponentRenderer.RenderSelectionBuffer(renderables, gameTime, World.ChunkManager, Camera,
                                                        DwarfGame.SpriteBatch, GraphicsDevice, DefaultShader);
                //GamePerformance.Instance.StopTrackPerformance("Render - Selection Buffer - Components");

                //GamePerformance.Instance.StartTrackPerformance("Render - Selection Buffer - Instances");
                InstanceRenderer.Flush(GraphicsDevice, DefaultShader, Camera,
                                       InstanceRenderMode.SelectionBuffer);
                //GamePerformance.Instance.StopTrackPerformance("Render - Selection Buffer - Instances");

                SelectionBuffer.End(GraphicsDevice);
            }


            #endregion



            // Start drawing the bloom effect
            if (GameSettings.Current.EnableGlow)
            {
                bloom.BeginDraw();
            }

            // Draw the sky
            GraphicsDevice.Clear(DefaultShader.FogColor);
            DrawSky(gameTime, Camera.ViewMatrix, 1.0f, DefaultShader.FogColor);



            DefaultShader.FogEnd   = GameSettings.Current.ChunkDrawDistance;
            DefaultShader.FogStart = GameSettings.Current.ChunkDrawDistance * 0.8f;

            CaveView = CaveView * 0.9f + TargetCaveView * 0.1f;
            DefaultShader.WindDirection = World.Weather.CurrentWind;
            DefaultShader.WindForce     = 0.0005f * (1.0f + (float)Math.Sin(World.Time.GetTotalSeconds() * 0.001f));
            // Draw the whole world, and make sure to handle slicing
            DefaultShader.ClipPlane       = new Vector4(slicePlane.Normal, slicePlane.D);
            DefaultShader.ClippingEnabled = true;
            //Blue ghost effect above the current slice.
            DefaultShader.GhostClippingEnabled = true;
            Draw3DThings(gameTime, DefaultShader, Camera.ViewMatrix);


            // Now we want to draw the water on top of everything else
            DefaultShader.ClippingEnabled      = true;
            DefaultShader.GhostClippingEnabled = false;

            //ComponentManager.CollisionManager.DebugDraw();

            DefaultShader.View                 = Camera.ViewMatrix;
            DefaultShader.Projection           = Camera.ProjectionMatrix;
            DefaultShader.GhostClippingEnabled = true;
            // Now draw all of the entities in the game
            DefaultShader.ClipPlane       = new Vector4(slicePlane.Normal, slicePlane.D);
            DefaultShader.ClippingEnabled = true;

            // Render simple geometry (boxes, etc.)
            Drawer3D.Render(GraphicsDevice, DefaultShader, Camera, World.PersistentData.Designations, World);

            DefaultShader.EnableShadows = false;

            DefaultShader.View = Camera.ViewMatrix;

            ComponentRenderer.Render(renderables, gameTime, World.ChunkManager,
                                     Camera,
                                     DwarfGame.SpriteBatch, GraphicsDevice, DefaultShader,
                                     ComponentRenderer.WaterRenderType.None, lastWaterHeight);
            InstanceRenderer.Flush(GraphicsDevice, DefaultShader, Camera, InstanceRenderMode.Normal);

            if (World.UserInterface.CurrentToolMode == "BuildZone" || // Todo: ??
                World.UserInterface.CurrentToolMode == "BuildWall")
            {
                DefaultShader.View       = Camera.ViewMatrix;
                DefaultShader.Projection = Camera.ProjectionMatrix;
                DefaultShader.SetTexturedTechnique();
                GraphicsDevice.BlendState = BlendState.NonPremultiplied;
            }

            WaterRenderer.DrawWater(
                GraphicsDevice,
                (float)gameTime.TotalGameTime.TotalSeconds,
                DefaultShader,
                Camera.ViewMatrix,
                GetReflectedCameraMatrix(wHeight),
                Camera.ProjectionMatrix,
                new Vector3(0.1f, 0.0f, 0.1f),
                Camera,
                World.ChunkManager);
            World.ParticleManager.Render(World, GraphicsDevice);
            DefaultShader.ClippingEnabled = false;

            if (UseFXAA && fxaa == null)
            {
                fxaa = new FXAA();
                fxaa.Initialize();
            }

            if (GameSettings.Current.EnableGlow)
            {
                if (UseFXAA)
                {
                    fxaa.Begin(DwarfTime.LastTime);
                }
                bloom.DrawTarget = UseFXAA ? fxaa.RenderTarget : null;

                bloom.Draw(gameTime.ToRealTime());
                if (UseFXAA)
                {
                    fxaa.End(DwarfTime.LastTime);
                }
            }
            else if (UseFXAA)
            {
                fxaa.End(DwarfTime.LastTime);
            }

            RasterizerState rasterizerState = new RasterizerState()
            {
                ScissorTestEnable = true
            };


            if (Debugger.Switches.DrawSelectionBuffer)
            {
                SelectionBuffer.DebugDraw(GraphicsDevice.Viewport.Bounds);
            }

            try
            {
                DwarfGame.SafeSpriteBatchBegin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, Drawer2D.PointMagLinearMin,
                                               null, rasterizerState, null, Matrix.Identity);
                //DwarfGame.SpriteBatch.Draw(Shadows.ShadowTexture, Vector2.Zero, Color.White);
                if (IsCameraUnderwater())
                {
                    Drawer2D.FillRect(DwarfGame.SpriteBatch, GraphicsDevice.Viewport.Bounds, new Color(10, 40, 60, 200));
                }

                Drawer2D.Render(DwarfGame.SpriteBatch, Camera, GraphicsDevice.Viewport);

                IndicatorManager.Render(gameTime);
            }
            finally
            {
                try
                {
                    DwarfGame.SpriteBatch.End();
                }
                catch (Exception exception)
                {
                    DwarfGame.SpriteBatch = new SpriteBatch(GraphicsDevice);
                }
            }

            if (Debugger.Switches.DrawComposites)
            {
                Vector2 offset = Vector2.Zero;
                foreach (var composite in CompositeLibrary.Composites)
                {
                    offset = composite.Value.DebugDraw(DwarfGame.SpriteBatch, (int)offset.X, (int)offset.Y);
                }
            }

            DwarfGame.SpriteBatch.GraphicsDevice.ScissorRectangle =
                DwarfGame.SpriteBatch.GraphicsDevice.Viewport.Bounds;

            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            GraphicsDevice.BlendState        = BlendState.Opaque;

            foreach (var module in World.UpdateSystems)
            {
                module.Render(gameTime, World.ChunkManager, Camera, DwarfGame.SpriteBatch, GraphicsDevice, DefaultShader);
            }

            lock (ScreenshotLock)
            {
                foreach (Screenshot shot in Screenshots)
                {
                    TakeScreenshot(shot.FileName, shot.Resolution);
                }

                Screenshots.Clear();
            }
        }
Beispiel #4
0
        public static Texture2D RenderPatternIcons(GraphicsDevice device, Microsoft.Xna.Framework.Content.ContentManager Content, Gui.TileSheetDefinition Sheet)
        {
            InitializeRailLibrary();

            var shader = new Shader(Content.Load <Effect>(ContentPaths.Shaders.TexturedShaders), true);

            var sqrt  = (int)(Math.Ceiling(Math.Sqrt(RailPatterns.Count)));
            var width = MathFunctions.NearestPowerOf2(sqrt * Sheet.TileWidth);

            var fitHorizontal = width / Sheet.TileWidth;
            var rowCount      = (int)Math.Ceiling((float)RailPatterns.Count / (float)fitHorizontal);
            var height        = MathFunctions.NearestPowerOf2(rowCount * Sheet.TileHeight);

            RenderTarget2D toReturn  = new RenderTarget2D(device, width, height, false, SurfaceFormat.Color, DepthFormat.Depth16, 0, RenderTargetUsage.PreserveContents);
            var            tileSheet = new SpriteSheet(ContentPaths.rail_tiles, 32);

            device.SetRenderTarget(toReturn);
            device.Clear(Color.Transparent);
            shader.SetTexturedTechnique();
            shader.MainTexture             = AssetManager.GetContentTexture(ContentPaths.rail_tiles);
            shader.SelfIlluminationEnabled = true;
            shader.SelfIlluminationTexture = AssetManager.GetContentTexture(ContentPaths.Terrain.terrain_illumination);
            shader.EnableShadows           = false;
            shader.EnableLighting          = false;
            shader.ClippingEnabled         = false;
            shader.CameraPosition          = new Vector3(-0.5f, 0.5f, 0.5f);
            shader.VertexColorTint         = Color.White;
            shader.LightRamp                = Color.White;
            shader.SunlightGradient         = AssetManager.GetContentTexture(ContentPaths.Gradients.sungradient);
            shader.AmbientOcclusionGradient = AssetManager.GetContentTexture(ContentPaths.Gradients.ambientgradient);
            shader.TorchlightGradient       = AssetManager.GetContentTexture(ContentPaths.Gradients.torchgradient);

            Viewport oldview = device.Viewport;
            int      rows    = height / Sheet.TileWidth;
            int      cols    = width / Sheet.TileWidth;

            device.ScissorRectangle  = new Rectangle(0, 0, Sheet.TileWidth, Sheet.TileHeight);
            device.RasterizerState   = RasterizerState.CullNone;
            device.DepthStencilState = DepthStencilState.Default;
            Vector3 half = Vector3.One * 0.5f;

            half = new Vector3(half.X, half.Y, half.Z);

            foreach (EffectPass pass in shader.CurrentTechnique.Passes)
            {
                int ID = 0;

                foreach (var type in RailPatterns)
                {
                    int row = ID / cols;
                    int col = ID % cols;

                    var xboundsMin = 0;
                    var xboundsMax = 0;
                    var yboundsMin = 0;
                    var yboundsMax = 0;

                    var primitive = new RawPrimitive();
                    foreach (var piece in type.Pieces)
                    {
                        var rawPiece = Library.GetRailPiece(piece.RailPiece);

                        var bounds = Vector4.Zero;
                        var uvs    = tileSheet.GenerateTileUVs(rawPiece.HasValue(out var raw) ? raw.Tile : Point.Zero, out bounds);
                        primitive.AddQuad(
                            Matrix.CreateRotationY((float)Math.PI * 0.5f * (float)piece.Orientation)
                            * Matrix.CreateTranslation(new Vector3(piece.Offset.X, 0.0f, piece.Offset.Y)),
                            Color.White, Color.White, uvs, bounds);

                        xboundsMin = Math.Min(xboundsMin, piece.Offset.X);
                        xboundsMax = Math.Max(xboundsMax, piece.Offset.X);
                        yboundsMin = Math.Min(yboundsMin, piece.Offset.Y);
                        yboundsMax = Math.Max(yboundsMax, piece.Offset.Y);
                    }

                    float xSize = xboundsMax - xboundsMin + 1;
                    float ySize = yboundsMax - yboundsMin + 1;

                    var cameraPos = new Vector3(xboundsMin + (xSize / 2), 2.0f, yboundsMax + 1.0f);

                    device.Viewport = new Viewport(col * Sheet.TileWidth, row * Sheet.TileHeight, Sheet.TileWidth, Sheet.TileHeight);
                    shader.View     = Matrix.CreateLookAt(cameraPos,
                                                          new Vector3((xboundsMin + (xSize / 2)), 0.0f, yboundsMin),
                                                          Vector3.UnitY);
                    shader.Projection     = Matrix.CreatePerspectiveFieldOfView(1.0f, 1.0f, 0.1f, 10);
                    shader.World          = Matrix.Identity;
                    shader.CameraPosition = cameraPos;
                    pass.Apply();
                    primitive.Render(device);

                    ++ID;
                }
            }
            device.Viewport = oldview;
            device.SetRenderTarget(null);
            return((Texture2D)toReturn);
        }
Beispiel #5
0
        public override void Flush(GraphicsDevice Device, Shader Effect, Camera Camera, InstanceRenderMode Mode)
        {
            if (InstanceCount == 0)
            {
                return;
            }

            if (NeedsRendered || (AtlasTexture != null && (AtlasTexture.IsDisposed || AtlasTexture.GraphicsDevice.IsDisposed)))
            {
                if (RawAtlas == null || RawAtlas.Textures.Count == 0)
                {
                    RebuildAtlas();
                    if (RawAtlas == null || RawAtlas.Textures.Count == 0)
                    {
                        // WTF.
                        InstanceCount = 0;
                        return;
                    }
                }

                AtlasTexture = new Texture2D(Device, RawAtlas.Dimensions.Width, RawAtlas.Dimensions.Height);

                foreach (var texture in RawAtlas.Textures)
                {
                    var realTexture = texture.RealTexture;
                    var textureData = new Color[realTexture.Width * realTexture.Height];
                    realTexture.GetData(textureData);

                    // Paste texture data into atlas.
                    AtlasTexture.SetData(0, texture.Rect, textureData, 0, realTexture.Width * realTexture.Height);
                }

                NeedsRendered = false;
            }

            if (InstanceBuffer == null)
            {
                InstanceBuffer = new DynamicVertexBuffer(Device, TiledInstancedVertex.VertexDeclaration, InstanceQueueSize, BufferUsage.None);
            }

            Device.RasterizerState = new RasterizerState {
                CullMode = CullMode.None
            };
            if (Mode == InstanceRenderMode.Normal)
            {
                Effect.SetTiledInstancedTechnique();
            }
            else
            {
                Effect.CurrentTechnique = Effect.Techniques[Shader.Technique.SelectionBufferTiledInstanced];
            }

            Effect.EnableWind      = RenderData.EnableWind;
            Effect.EnableLighting  = true;
            Effect.VertexColorTint = Color.White;

            if (RenderData.Model.VertexBuffer == null || RenderData.Model.IndexBuffer == null ||
                (RenderData.Model.VertexBuffer != null && RenderData.Model.VertexBuffer.IsContentLost) ||
                (RenderData.Model.IndexBuffer != null && RenderData.Model.IndexBuffer.IsContentLost))
            {
                RenderData.Model.ResetBuffer(Device);
            }

            Device.Indices = RenderData.Model.IndexBuffer;

            BlendState blendState = Device.BlendState;

            Device.BlendState = Mode == InstanceRenderMode.Normal ? BlendState.NonPremultiplied : BlendState.Opaque;

            Effect.MainTexture = AtlasTexture;
            Effect.LightRamp   = Color.White;

            InstanceBuffer.SetData(Instances, 0, InstanceCount, SetDataOptions.Discard);
            Device.SetVertexBuffers(RenderData.Model.VertexBuffer, new VertexBufferBinding(InstanceBuffer, 0, 1));

            var ghostEnabled = Effect.GhostClippingEnabled;

            Effect.GhostClippingEnabled = RenderData.EnableGhostClipping && ghostEnabled;

            foreach (EffectPass pass in Effect.CurrentTechnique.Passes)
            {
                pass.Apply();
                Device.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0,
                                               RenderData.Model.VertexCount, 0,
                                               RenderData.Model.Indexes.Length / 3,
                                               InstanceCount);
            }

            Effect.GhostClippingEnabled = ghostEnabled;
            Effect.SetTexturedTechnique();
            Effect.World      = Matrix.Identity;
            Device.BlendState = blendState;
            Effect.EnableWind = false;

            InstanceCount = 0;
        }
Beispiel #6
0
        /// <summary>
        /// Called when a frame is to be drawn to the screen
        /// </summary>
        /// <param name="gameTime">The current time</param>
        public void Render(DwarfTime gameTime)
        {
            if (!ShowingWorld)
            {
                return;
            }

            var frustum     = Camera.GetDrawFrustum();
            var renderables = EnumerateIntersectingObjects(frustum)
                              .Where(r => r.IsVisible && !ChunkManager.IsAboveCullPlane(r.GetBoundingBox()));

            // Controls the sky fog
            float x = (1.0f - Sky.TimeOfDay);

            x = x * x;
            DefaultShader.FogColor       = new Color(0.32f * x, 0.58f * x, 0.9f * x);
            DefaultShader.LightPositions = LightPositions;

            CompositeLibrary.Render(GraphicsDevice);
            CompositeLibrary.Update();

            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            GraphicsDevice.BlendState        = BlendState.Opaque;

            // Computes the water height.
            float wHeight = WaterRenderer.GetVisibleWaterHeight(ChunkManager, Camera, GraphicsDevice.Viewport,
                                                                lastWaterHeight);

            lastWaterHeight = wHeight;

            // Draw reflection/refraction images
            WaterRenderer.DrawReflectionMap(renderables, gameTime, this, wHeight - 0.1f,
                                            GetReflectedCameraMatrix(wHeight),
                                            DefaultShader, GraphicsDevice);


            #region Draw Selection Buffer.

            if (SelectionBuffer == null)
            {
                SelectionBuffer = new SelectionBuffer(8, GraphicsDevice);
            }

            GraphicsDevice.RasterizerState   = RasterizerState.CullNone;
            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            GraphicsDevice.BlendState        = BlendState.Opaque;

            Plane slicePlane = WaterRenderer.CreatePlane(SlicePlane, new Vector3(0, -1, 0), Camera.ViewMatrix, false);

            if (SelectionBuffer.Begin(GraphicsDevice))
            {
                // Draw the whole world, and make sure to handle slicing
                DefaultShader.ClipPlane       = new Vector4(slicePlane.Normal, slicePlane.D);
                DefaultShader.ClippingEnabled = true;
                DefaultShader.View            = Camera.ViewMatrix;
                DefaultShader.Projection      = Camera.ProjectionMatrix;
                DefaultShader.World           = Matrix.Identity;

                //GamePerformance.Instance.StartTrackPerformance("Render - Selection Buffer - Chunks");
                ChunkRenderer.RenderSelectionBuffer(DefaultShader, GraphicsDevice, Camera.ViewMatrix);
                //GamePerformance.Instance.StopTrackPerformance("Render - Selection Buffer - Chunks");

                //GamePerformance.Instance.StartTrackPerformance("Render - Selection Buffer - Components");
                ComponentRenderer.RenderSelectionBuffer(renderables, gameTime, ChunkManager, Camera,
                                                        DwarfGame.SpriteBatch, GraphicsDevice, DefaultShader);
                //GamePerformance.Instance.StopTrackPerformance("Render - Selection Buffer - Components");

                //GamePerformance.Instance.StartTrackPerformance("Render - Selection Buffer - Instances");
                InstanceRenderer.Flush(GraphicsDevice, DefaultShader, Camera,
                                       InstanceRenderMode.SelectionBuffer);
                //GamePerformance.Instance.StopTrackPerformance("Render - Selection Buffer - Instances");

                SelectionBuffer.End(GraphicsDevice);
            }


            #endregion



            // Start drawing the bloom effect
            if (GameSettings.Default.EnableGlow)
            {
                bloom.BeginDraw();
            }

            // Draw the sky
            GraphicsDevice.Clear(DefaultShader.FogColor);
            DrawSky(gameTime, Camera.ViewMatrix, 1.0f, DefaultShader.FogColor);

            // Defines the current slice for the GPU
            float level = ChunkManager.World.Master.MaxViewingLevel + 0.25f;
            if (level > VoxelConstants.ChunkSizeY)
            {
                level = 1000;
            }

            SlicePlane = level;

            DefaultShader.WindDirection = Weather.CurrentWind;
            DefaultShader.WindForce     = 0.0005f * (1.0f + (float)Math.Sin(Time.GetTotalSeconds() * 0.001f));
            // Draw the whole world, and make sure to handle slicing
            DefaultShader.ClipPlane       = new Vector4(slicePlane.Normal, slicePlane.D);
            DefaultShader.ClippingEnabled = true;
            //Blue ghost effect above the current slice.
            DefaultShader.GhostClippingEnabled = true;
            Draw3DThings(gameTime, DefaultShader, Camera.ViewMatrix);

            // Now we want to draw the water on top of everything else
            DefaultShader.ClippingEnabled      = true;
            DefaultShader.GhostClippingEnabled = false;

            //ComponentManager.CollisionManager.DebugDraw();

            DefaultShader.View                 = Camera.ViewMatrix;
            DefaultShader.Projection           = Camera.ProjectionMatrix;
            DefaultShader.GhostClippingEnabled = true;
            // Now draw all of the entities in the game
            DefaultShader.ClipPlane       = new Vector4(slicePlane.Normal, slicePlane.D);
            DefaultShader.ClippingEnabled = true;

            if (Debugger.Switches.DrawOcttree)
            {
                foreach (var box in OctTree.EnumerateBounds(frustum))
                {
                    Drawer3D.DrawBox(box.Item2, Color.Yellow, 1.0f / (float)(box.Item1 + 1), false);
                }
            }

            // Render simple geometry (boxes, etc.)
            Drawer3D.Render(GraphicsDevice, DefaultShader, Camera, DesignationDrawer, PlayerFaction.Designations, this);

            DefaultShader.EnableShadows = false;

            DefaultShader.View = Camera.ViewMatrix;

            ComponentRenderer.Render(renderables, gameTime, ChunkManager,
                                     Camera,
                                     DwarfGame.SpriteBatch, GraphicsDevice, DefaultShader,
                                     ComponentRenderer.WaterRenderType.None, lastWaterHeight);
            InstanceRenderer.Flush(GraphicsDevice, DefaultShader, Camera, InstanceRenderMode.Normal);

            if (Master.CurrentToolMode == GameMaster.ToolMode.BuildZone ||
                Master.CurrentToolMode == GameMaster.ToolMode.BuildWall ||
                Master.CurrentToolMode == GameMaster.ToolMode.BuildObject)
            {
                DefaultShader.View       = Camera.ViewMatrix;
                DefaultShader.Projection = Camera.ProjectionMatrix;
                DefaultShader.SetTexturedTechnique();
                GraphicsDevice.BlendState = BlendState.NonPremultiplied;
            }

            WaterRenderer.DrawWater(
                GraphicsDevice,
                (float)gameTime.TotalGameTime.TotalSeconds,
                DefaultShader,
                Camera.ViewMatrix,
                GetReflectedCameraMatrix(wHeight),
                Camera.ProjectionMatrix,
                new Vector3(0.1f, 0.0f, 0.1f),
                Camera,
                ChunkManager);
            ParticleManager.Render(this, GraphicsDevice);
            DefaultShader.ClippingEnabled = false;

            if (GameSettings.Default.EnableGlow)
            {
                bloom.DrawTarget = UseFXAA ? fxaa.RenderTarget : null;

                if (UseFXAA)
                {
                    fxaa.Begin(DwarfTime.LastTime);
                }
                bloom.Draw(gameTime.ToRealTime());
                if (UseFXAA)
                {
                    fxaa.End(DwarfTime.LastTime);
                }
            }
            else if (UseFXAA)
            {
                fxaa.End(DwarfTime.LastTime);
            }

            RasterizerState rasterizerState = new RasterizerState()
            {
                ScissorTestEnable = true
            };


            if (Debugger.Switches.DrawSelectionBuffer)
            {
                SelectionBuffer.DebugDraw(GraphicsDevice.Viewport.Bounds);
            }

            try
            {
                DwarfGame.SafeSpriteBatchBegin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, Drawer2D.PointMagLinearMin,
                                               null, rasterizerState, null, Matrix.Identity);
                //DwarfGame.SpriteBatch.Draw(Shadows.ShadowTexture, Vector2.Zero, Color.White);
                if (IsCameraUnderwater())
                {
                    Drawer2D.FillRect(DwarfGame.SpriteBatch, GraphicsDevice.Viewport.Bounds, new Color(10, 40, 60, 200));
                }

                Drawer2D.Render(DwarfGame.SpriteBatch, Camera, GraphicsDevice.Viewport);

                IndicatorManager.Render(gameTime);
            }
            finally
            {
                DwarfGame.SpriteBatch.End();
            }

            if (Debugger.Switches.DrawComposites)
            {
                Vector2 offset = Vector2.Zero;
                foreach (var composite in CompositeLibrary.Composites)
                {
                    offset = composite.Value.DebugDraw(DwarfGame.SpriteBatch, (int)offset.X, (int)offset.Y);
                }
            }


            Master.Render(Game, gameTime, GraphicsDevice);

            DwarfGame.SpriteBatch.GraphicsDevice.ScissorRectangle =
                DwarfGame.SpriteBatch.GraphicsDevice.Viewport.Bounds;


            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            GraphicsDevice.BlendState        = BlendState.Opaque;

            lock (ScreenshotLock)
            {
                foreach (Screenshot shot in Screenshots)
                {
                    TakeScreenshot(shot.FileName, shot.Resolution);
                }

                Screenshots.Clear();
            }
        }