Пример #1
0
        /// <summary>
        /// Call this once to initialise the renderer
        /// </summary>
        public virtual void Initialize(HostInterface CurrentHost, BaseOptions CurrentOptions)
        {
            currentHost    = CurrentHost;
            currentOptions = CurrentOptions;

            Background     = new Background(this);
            Fog            = new Fog();
            OpenGlString   = new OpenGlString(this);
            TextureManager = new TextureManager(currentHost);
            Cube           = new Cube(this);
            Rectangle      = new Rectangle(this);
            Loading        = new Loading(this);
            Keys           = new Keys(this);
            MotionBlur     = new MotionBlur(this);

            StaticObjectStates  = new List <ObjectState>();
            DynamicObjectStates = new List <ObjectState>();
            VisibleObjects      = new VisibleObjectLibrary(currentHost, Camera, currentOptions, this);
            try
            {
                DefaultShader = new Shader("default", "default", true);
                DefaultShader.Activate();
                DefaultShader.Deactivate();
            }
            catch
            {
                CurrentHost.AddMessage(MessageType.Error, false, "Initialising the default shaders failed- Falling back to legacy openGL.");
                CurrentOptions.IsUseNewRenderer = false;
            }

            GL.ClearColor(0.67f, 0.67f, 0.67f, 1.0f);
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
            GL.Enable(EnableCap.DepthTest);
            GL.DepthFunc(DepthFunction.Lequal);
            SetBlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
            GL.Hint(HintTarget.FogHint, HintMode.Fastest);
            GL.Hint(HintTarget.LineSmoothHint, HintMode.Fastest);
            GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Fastest);
            GL.Hint(HintTarget.PointSmoothHint, HintMode.Fastest);
            GL.Hint(HintTarget.PolygonSmoothHint, HintMode.Fastest);
            GL.Hint(HintTarget.GenerateMipmapHint, HintMode.Nicest);
            GL.Enable(EnableCap.CullFace);
            GL.CullFace(CullFaceMode.Front);
            GL.Disable(EnableCap.Texture2D);
            GL.Disable(EnableCap.Dither);
            GL.Disable(EnableCap.Lighting);
            GL.Disable(EnableCap.Fog);
            GL.Fog(FogParameter.FogMode, (int)FogMode.Linear);
        }
Пример #2
0
        private void RenderOverlays()
        {
            //Initialize openGL
            SetBlendFunc();
            PushMatrix(MatrixMode.Projection);
            Matrix4D.CreateOrthographicOffCenter(0.0f, Screen.Width, Screen.Height, 0.0f, -1.0f, 1.0f, out CurrentProjectionMatrix);
            PushMatrix(MatrixMode.Modelview);
            CurrentViewMatrix = Matrix4D.Identity;

            CultureInfo culture = CultureInfo.InvariantCulture;

            if (OptionInterface)
            {
                string[][] keys;

                if (VisibleObjects.Objects.Count == 0 && ObjectManager.AnimatedWorldObjectsUsed == 0)
                {
                    keys = new[] { new[] { "F7" }, new[] { "F8" }, new[] { "F10" } };
                    Keys.Render(4, 4, 20, Fonts.SmallFont, keys);
                    OpenGlString.Draw(Fonts.SmallFont, "Open one or more objects", new Vector2(32, 4), TextAlignment.TopLeft, TextColor);
                    OpenGlString.Draw(Fonts.SmallFont, "Display the options window", new Vector2(32, 24), TextAlignment.TopLeft, TextColor);
                    OpenGlString.Draw(Fonts.SmallFont, "Display the train settings window", new Vector2(32, 44), TextAlignment.TopLeft, TextColor);
                    OpenGlString.Draw(Fonts.SmallFont, $"v{Application.ProductVersion}", new Vector2(Screen.Width - 8, Screen.Height - 20), TextAlignment.TopLeft, TextColor);
                    if (Interface.LogMessages.Count == 1)
                    {
                        Keys.Render(4, 64, 20, Fonts.SmallFont, new[] { new[] { "F9" } });

                        if (Interface.LogMessages[0].Type != MessageType.Information)
                        {
                            OpenGlString.Draw(Fonts.SmallFont, "Display the 1 error message recently generated.", new Vector2(32, 64), TextAlignment.TopLeft, new Color128(1.0f, 0.5f, 0.5f));
                        }
                        else
                        {
                            //If all of our messages are information, then print the message text in grey
                            OpenGlString.Draw(Fonts.SmallFont, "Display the 1 message recently generated.", new Vector2(32, 64), TextAlignment.TopLeft, TextColor);
                        }
                    }
                    else if (Interface.LogMessages.Count > 1)
                    {
                        Keys.Render(4, 64, 20, Fonts.SmallFont, new[] { new[] { "F9" } });
                        bool error = Interface.LogMessages.Any(x => x.Type != MessageType.Information);

                        if (error)
                        {
                            OpenGlString.Draw(Fonts.SmallFont, $"Display the {Interface.LogMessages.Count.ToString(culture)} error messages recently generated.", new Vector2(32, 64), TextAlignment.TopLeft, new Color128(1.0f, 0.5f, 0.5f));
                        }
                        else
                        {
                            OpenGlString.Draw(Fonts.SmallFont, $"Display the {Interface.LogMessages.Count.ToString(culture)} messages recently generated.", new Vector2(32, 64), TextAlignment.TopLeft, TextColor);
                        }
                    }
                }
                else
                {
                    OpenGlString.Draw(Fonts.SmallFont, $"Position: {Camera.AbsolutePosition.X.ToString("0.00", culture)}, {Camera.AbsolutePosition.Y.ToString("0.00", culture)}, {Camera.AbsolutePosition.Z.ToString("0.00", culture)}", new Vector2((int)(0.5 * Screen.Width - 88), 4), TextAlignment.TopLeft, TextColor);
                    OpenGlString.Draw(Fonts.SmallFont, $"Renderer: {(AvailableNewRenderer ? "New (GL 3.0)" : "Old (GL 1.2)")}", new Vector2((int)(0.5 * Screen.Width - 88), 24), TextAlignment.TopLeft, TextColor);
                    keys = new[] { new[] { "F5" }, new[] { "F7" }, new[] { "del" }, new[] { "F8" }, new[] { "F10" } };
                    Keys.Render(4, 4, 24, Fonts.SmallFont, keys);
                    OpenGlString.Draw(Fonts.SmallFont, "Reload the currently open objects", new Vector2(32, 4), TextAlignment.TopLeft, TextColor);
                    OpenGlString.Draw(Fonts.SmallFont, "Open additional objects", new Vector2(32, 24), TextAlignment.TopLeft, TextColor);
                    OpenGlString.Draw(Fonts.SmallFont, "Clear currently open objects", new Vector2(32, 44), TextAlignment.TopLeft, TextColor);
                    OpenGlString.Draw(Fonts.SmallFont, "Display the options window", new Vector2(32, 64), TextAlignment.TopLeft, TextColor);
                    OpenGlString.Draw(Fonts.SmallFont, "Display the train settings window", new Vector2(32, 84), TextAlignment.TopLeft, TextColor);

                    keys = new[] { new[] { "F" }, new[] { "N" }, new[] { "L" }, new[] { "G" }, new[] { "B" }, new[] { "I" }, new[] { "R" } };
                    Keys.Render(Screen.Width - 20, 4, 16, Fonts.SmallFont, keys);
                    keys = new[] { new[] { "F11" } };
                    Keys.Render(Screen.Width - 36, 124, 32, Fonts.SmallFont, keys);
                    keys = new[] { new[] { "R" } };
                    Keys.Render(Screen.Width - 20, 144, 16, Fonts.SmallFont, keys);
                    OpenGlString.Draw(Fonts.SmallFont, $"WireFrame: {(OptionWireFrame ? "on" : "off")}", new Vector2(Screen.Width - 28, 4), TextAlignment.TopRight, TextColor);
                    OpenGlString.Draw(Fonts.SmallFont, $"Normals: {(OptionNormals ? "on" : "off")}", new Vector2(Screen.Width - 28, 24), TextAlignment.TopRight, TextColor);
                    OpenGlString.Draw(Fonts.SmallFont, $"Lighting: {(Program.LightingTarget == 0 ? "night" : "day")}", new Vector2(Screen.Width - 28, 44), TextAlignment.TopRight, TextColor);
                    OpenGlString.Draw(Fonts.SmallFont, $"Grid: {(OptionCoordinateSystem ? "on" : "off")}", new Vector2(Screen.Width - 28, 64), TextAlignment.TopRight, TextColor);
                    OpenGlString.Draw(Fonts.SmallFont, $"Background: {GetBackgroundColorName()}", new Vector2(Screen.Width - 28, 84), TextAlignment.TopRight, TextColor);
                    OpenGlString.Draw(Fonts.SmallFont, "Hide interface:", new Vector2(Screen.Width - 28, 104), TextAlignment.TopRight, TextColor);
                    OpenGlString.Draw(Fonts.SmallFont, $"{(RenderStatsOverlay ? "Hide" : "Show")} renderer statistics", new Vector2(Screen.Width - 44, 124), TextAlignment.TopRight, TextColor);
                    OpenGlString.Draw(Fonts.SmallFont, "Switch renderer type:", new Vector2(Screen.Width - 28, 144), TextAlignment.TopRight, TextColor);

                    keys = new[] { new[] { null, "W", null }, new[] { "A", "S", "D" } };
                    Keys.Render(4, Screen.Height - 40, 16, Fonts.SmallFont, keys);

                    keys = new[] { new[] { null, "↑", null }, new[] { "←", "↓", "→" } };
                    Keys.Render((int)(0.5 * Screen.Width - 28), Screen.Height - 40, 16, Fonts.SmallFont, keys);

                    keys = new[] { new[] { null, "8", "9" }, new[] { "4", "5", "6" }, new[] { null, "2", "3" } };
                    Keys.Render(Screen.Width - 60, Screen.Height - 60, 16, Fonts.SmallFont, keys);

                    if (Interface.LogMessages.Count == 1)
                    {
                        Keys.Render(4, 112, 20, Fonts.SmallFont, new[] { new[] { "F9" } });

                        if (Interface.LogMessages[0].Type != MessageType.Information)
                        {
                            OpenGlString.Draw(Fonts.SmallFont, "Display the 1 error message recently generated.", new Vector2(32, 112), TextAlignment.TopLeft, new Color128(1.0f, 0.5f, 0.5f));
                        }
                        else
                        {
                            //If all of our messages are information, then print the message text in grey
                            OpenGlString.Draw(Fonts.SmallFont, "Display the 1 message recently generated.", new Vector2(32, 112), TextAlignment.TopLeft, TextColor);
                        }
                    }
                    else if (Interface.LogMessages.Count > 1)
                    {
                        Keys.Render(4, 112, 20, Fonts.SmallFont, new[] { new[] { "F9" } });
                        bool error = Interface.LogMessages.Any(x => x.Type != MessageType.Information);

                        if (error)
                        {
                            OpenGlString.Draw(Fonts.SmallFont, $"Display the {Interface.LogMessages.Count.ToString(culture)} error messages recently generated.", new Vector2(32, 112), TextAlignment.TopLeft, new Color128(1.0f, 0.5f, 0.5f));
                        }
                        else
                        {
                            OpenGlString.Draw(Fonts.SmallFont, $"Display the {Interface.LogMessages.Count.ToString(culture)} messages recently generated.", new Vector2(32, 112), TextAlignment.TopLeft, TextColor);
                        }
                    }

                    if (RenderStatsOverlay)
                    {
                        Keys.Render(4, Screen.Height - 126, 116, Fonts.SmallFont, new[] { new[] { "Renderer Statistics" } });
                        OpenGlString.Draw(Fonts.SmallFont, $"Total static objects: {VisibleObjects.Objects.Count}", new Vector2(4, Screen.Height - 112), TextAlignment.TopLeft, Color128.White, true);
                        OpenGlString.Draw(Fonts.SmallFont, $"Total animated objects: {ObjectManager.AnimatedWorldObjectsUsed}", new Vector2(4, Screen.Height - 100), TextAlignment.TopLeft, Color128.White, true);
                        OpenGlString.Draw(Fonts.SmallFont, $"Current frame rate: {FrameRate.ToString("0.0", culture)}fps", new Vector2(4, Screen.Height - 88), TextAlignment.TopLeft, Color128.White, true);
                        OpenGlString.Draw(Fonts.SmallFont, $"Total opaque faces: {VisibleObjects.OpaqueFaces.Count}", new Vector2(4, Screen.Height - 76), TextAlignment.TopLeft, Color128.White, true);
                        OpenGlString.Draw(Fonts.SmallFont, $"Total alpha faces: {VisibleObjects.AlphaFaces.Count}", new Vector2(4, Screen.Height - 64), TextAlignment.TopLeft, Color128.White, true);
                    }
                }
            }

            // finalize
            PopMatrix(MatrixMode.Projection);
            PopMatrix(MatrixMode.Modelview);
        }
Пример #3
0
        private void RenderOverlays()
        {
            //Initialize openGL
            SetBlendFunc();
            PushMatrix(MatrixMode.Projection);
            Matrix4D.CreateOrthographicOffCenter(0.0f, Screen.Width, Screen.Height, 0.0f, -1.0f, 1.0f, out CurrentProjectionMatrix);
            PushMatrix(MatrixMode.Modelview);
            CurrentViewMatrix = Matrix4D.Identity;

            CultureInfo culture = CultureInfo.InvariantCulture;

            // marker
            if (OptionInterface)
            {
                int y = 150;

                foreach (Texture t in Marker.MarkerTextures)
                {
                    if (Program.CurrentHost.LoadTexture(t, OpenGlTextureWrapMode.ClampClamp))
                    {
                        int w = t.Width;
                        int h = t.Height;
                        GL.Color4(1.0, 1.0, 1.0, 1.0);
                        Rectangle.Draw(t, new Vector2(Screen.Width - w - 8, y), new Vector2(w, h));
                        y += h + 8;
                    }
                }
            }

            if (!Program.CurrentlyLoading)
            {
                string[][] keys;

                if (VisibleObjects.Objects.Count == 0 && ObjectManager.AnimatedWorldObjectsUsed == 0)
                {
                    keys = new[] { new[] { "F7" }, new[] { "F8" } };
                    Keys.Render(4, 4, 20, Fonts.SmallFont, keys);
                    OpenGlString.Draw(Fonts.SmallFont, "Open route", new Point(32, 4), TextAlignment.TopLeft, Color128.White);
                    OpenGlString.Draw(Fonts.SmallFont, "Display the options window", new Point(32, 24), TextAlignment.TopLeft, Color128.White);
                    OpenGlString.Draw(Fonts.SmallFont, $"v{Application.ProductVersion}", new Point(Screen.Width - 8, Screen.Height - 20), TextAlignment.TopLeft, Color128.White);
                }
                else if (OptionInterface)
                {
                    // keys
                    keys = new[] { new[] { "F5" }, new[] { "F7" }, new[] { "F8" } };
                    Keys.Render(4, 4, 24, Fonts.SmallFont, keys);
                    OpenGlString.Draw(Fonts.SmallFont, "Reload route", new Point(32, 4), TextAlignment.TopLeft, Color128.White, true);
                    OpenGlString.Draw(Fonts.SmallFont, "Open route", new Point(32, 24), TextAlignment.TopLeft, Color128.White, true);
                    OpenGlString.Draw(Fonts.SmallFont, "Display the options window", new Point(32, 44), TextAlignment.TopLeft, Color128.White, true);

                    keys = new[] { new[] { "F" }, new[] { "N" }, new[] { "E" }, new[] { "C" }, new[] { "M" }, new[] { "I" } };
                    Keys.Render(Screen.Width - 20, 4, 16, Fonts.SmallFont, keys);
                    OpenGlString.Draw(Fonts.SmallFont, "WireFrame:", new Point(Screen.Width - 32, 4), TextAlignment.TopRight, Color128.White, true);
                    OpenGlString.Draw(Fonts.SmallFont, "Normals:", new Point(Screen.Width - 32, 24), TextAlignment.TopRight, Color128.White, true);
                    OpenGlString.Draw(Fonts.SmallFont, "Events:", new Point(Screen.Width - 32, 44), TextAlignment.TopRight, Color128.White, true);
                    OpenGlString.Draw(Fonts.SmallFont, "CPU:", new Point(Screen.Width - 32, 64), TextAlignment.TopRight, Color128.White, true);
                    OpenGlString.Draw(Fonts.SmallFont, "Mute:", new Point(Screen.Width - 32, 84), TextAlignment.TopRight, Color128.White, true);
                    OpenGlString.Draw(Fonts.SmallFont, "Hide interface:", new Point(Screen.Width - 32, 104), TextAlignment.TopRight, Color128.White, true);
                    OpenGlString.Draw(Fonts.SmallFont, $"{(RenderStatsOverlay ? "Hide" : "Show")} renderer statistics", new Point(Screen.Width - 32, 124), TextAlignment.TopRight, Color128.White, true);
                    OpenGlString.Draw(Fonts.SmallFont, $"Switch renderer type:", new Point(Screen.Width - 32, 144), TextAlignment.TopRight, Color128.White, true);

                    keys = new[] { new[] { "F10" } };
                    Keys.Render(Screen.Width - 32, 124, 30, Fonts.SmallFont, keys);

                    keys = new[] { new[] { "R" } };
                    Keys.Render(Screen.Width - 20, 144, 16, Fonts.SmallFont, keys);

                    keys = new[] { new[] { null, "W", null }, new[] { "A", "S", "D" } };
                    Keys.Render(4, Screen.Height - 40, 16, Fonts.SmallFont, keys);

                    keys = new[] { new[] { null, "↑", null }, new[] { "←", "↓", "→" } };
                    Keys.Render(0 * Screen.Width - 48, Screen.Height - 40, 16, Fonts.SmallFont, keys);

                    keys = new[] { new[] { "P↑" }, new[] { "P↓" } };
                    Keys.Render((int)(0.5 * Screen.Width + 32), Screen.Height - 40, 24, Fonts.SmallFont, keys);

                    keys = new[] { new[] { null, "/", "*" }, new[] { "7", "8", "9" }, new[] { "4", "5", "6" }, new[] { "1", "2", "3" }, new[] { null, "0", "." } };
                    Keys.Render(Screen.Width - 60, Screen.Height - 100, 16, Fonts.SmallFont, keys);

                    if (Program.JumpToPositionEnabled)
                    {
                        OpenGlString.Draw(Fonts.SmallFont, "Jump to track position:", new Point(4, 80), TextAlignment.TopLeft, Color128.White, true);

                        double distance;

                        if (double.TryParse(Program.JumpToPositionValue, out distance))
                        {
                            if (distance < Program.MinimumJumpToPositionValue - 100)
                            {
                                OpenGlString.Draw(Fonts.SmallFont, (Environment.TickCount % 1000 <= 500 ? $"{Program.JumpToPositionValue}_" : Program.JumpToPositionValue), new Point(4, 100), TextAlignment.TopLeft, Color128.Red, true);
                            }
                            else
                            {
                                OpenGlString.Draw(Fonts.SmallFont, (Environment.TickCount % 1000 <= 500 ? $"{Program.JumpToPositionValue}_" : Program.JumpToPositionValue), new Point(4, 100), TextAlignment.TopLeft, distance > Program.CurrentRoute.Tracks[0].Elements[Program.CurrentRoute.Tracks[0].Elements.Length - 1].StartingTrackPosition + 100 ? Color128.Red : Color128.Yellow, true);
                            }
                        }
                    }

                    // info
                    double x = 0.5 * Screen.Width - 256.0;
                    OpenGlString.Draw(Fonts.SmallFont, $"Position: {GetLengthString(Camera.Alignment.TrackPosition)} (X={GetLengthString(Camera.Alignment.Position.X)}, Y={GetLengthString(Camera.Alignment.Position.Y)}), Orientation: (Yaw={(Camera.Alignment.Yaw * 57.2957795130824).ToString("0.00", culture)}°, Pitch={(Camera.Alignment.Pitch * 57.2957795130824).ToString("0.00", culture)}°, Roll={(Camera.Alignment.Roll * 57.2957795130824).ToString("0.00", culture)}°)", new Point((int)x, 4), TextAlignment.TopLeft, Color128.White, true);
                    OpenGlString.Draw(Fonts.SmallFont, $"Radius: {GetLengthString(CameraTrackFollower.CurveRadius)}, Cant: {(1000.0 * CameraTrackFollower.CurveCant).ToString("0", culture)} mm, Adhesion={(100.0 * CameraTrackFollower.AdhesionMultiplier).ToString("0", culture)}" + " , Rain intensity= " + CameraTrackFollower.RainIntensity + "%", new Point((int)x, 20), TextAlignment.TopLeft, Color128.White, true);
                    OpenGlString.Draw(Fonts.SmallFont, $"Renderer: {(AvailableNewRenderer ? "New (GL 3.0)" : "Old (GL 1.2)")}", new Point((int)x, 40), TextAlignment.TopLeft, Color128.White, true);

                    if (Program.CurrentStation >= 0)
                    {
                        StringBuilder t = new StringBuilder();
                        t.Append(Program.CurrentRoute.Stations[Program.CurrentStation].Name);

                        if (Program.CurrentRoute.Stations[Program.CurrentStation].ArrivalTime >= 0.0)
                        {
                            t.Append($", Arrival: {GetTime(Program.CurrentRoute.Stations[Program.CurrentStation].ArrivalTime)}");
                        }

                        if (Program.CurrentRoute.Stations[Program.CurrentStation].DepartureTime >= 0.0)
                        {
                            t.Append($", Departure: {GetTime(Program.CurrentRoute.Stations[Program.CurrentStation].DepartureTime)}");
                        }

                        if (Program.CurrentRoute.Stations[Program.CurrentStation].OpenLeftDoors & Program.CurrentRoute.Stations[Program.CurrentStation].OpenRightDoors)
                        {
                            t.Append(", [L][R]");
                        }
                        else if (Program.CurrentRoute.Stations[Program.CurrentStation].OpenLeftDoors)
                        {
                            t.Append(", [L][-]");
                        }
                        else if (Program.CurrentRoute.Stations[Program.CurrentStation].OpenRightDoors)
                        {
                            t.Append(", [-][R]");
                        }
                        else
                        {
                            t.Append(", [-][-]");
                        }

                        switch (Program.CurrentRoute.Stations[Program.CurrentStation].StopMode)
                        {
                        case StationStopMode.AllStop:
                            t.Append(", Stop");
                            break;

                        case StationStopMode.AllPass:
                            t.Append(", Pass");
                            break;

                        case StationStopMode.PlayerStop:
                            t.Append(", Player stops - others pass");
                            break;

                        case StationStopMode.PlayerPass:
                            t.Append(", Player passes - others stop");
                            break;
                        }

                        switch (Program.CurrentRoute.Stations[Program.CurrentStation].Type)
                        {
                        case StationType.ChangeEnds:
                            t.Append(", Change ends");
                            break;

                        case StationType.Jump:
                            t.Append(", then Jumps to " + Program.CurrentRoute.Stations[Program.CurrentRoute.Stations[Program.CurrentStation].JumpIndex].Name);
                            break;
                        }

                        t.Append(", Ratio=").Append((100.0 * Program.CurrentRoute.Stations[Program.CurrentStation].PassengerRatio).ToString("0", culture)).Append("%");

                        OpenGlString.Draw(Fonts.SmallFont, t.ToString(), new Point((int)x, 60), TextAlignment.TopLeft, Color128.White, true);
                    }

                    if (Interface.LogMessages.Count == 1)
                    {
                        keys = new[] { new[] { "F9" } };
                        Keys.Render(4, 72, 24, Fonts.SmallFont, keys);

                        if (Interface.LogMessages[0].Type != MessageType.Information)
                        {
                            OpenGlString.Draw(Fonts.SmallFont, "Display the 1 error message recently generated.", new Point(32, 72), TextAlignment.TopLeft, Color128.Red, true);
                        }
                        else
                        {
                            //If all of our messages are information, then print the message text in grey
                            OpenGlString.Draw(Fonts.SmallFont, "Display the 1 message recently generated.", new Point(32, 72), TextAlignment.TopLeft, Color128.White, true);
                        }
                    }
                    else if (Interface.LogMessages.Count > 1)
                    {
                        Keys.Render(4, 72, 24, Fonts.SmallFont, new[] { new[] { "F9" } });
                        bool error = Interface.LogMessages.Any(m => m.Type != MessageType.Information);

                        if (error)
                        {
                            OpenGlString.Draw(Fonts.SmallFont, $"Display the {Interface.LogMessages.Count} error messages recently generated.", new Point(32, 72), TextAlignment.TopLeft, Color128.Red, true);
                        }
                        else
                        {
                            OpenGlString.Draw(Fonts.SmallFont, $"Display the {Interface.LogMessages.Count} messages recently generated.", new Point(32, 72), TextAlignment.TopLeft, Color128.White, true);
                        }
                    }

                    if (RenderStatsOverlay)
                    {
                        Keys.Render(4, Screen.Height - 126, 116, Fonts.SmallFont, new[] { new[] { "Renderer Statistics" } });
                        OpenGlString.Draw(Fonts.SmallFont, $"Total static objects: {VisibleObjects.Objects.Count}", new Point(4, Screen.Height - 112), TextAlignment.TopLeft, Color128.White, true);
                        OpenGlString.Draw(Fonts.SmallFont, $"Total animated objects: {ObjectManager.AnimatedWorldObjectsUsed}", new Point(4, Screen.Height - 100), TextAlignment.TopLeft, Color128.White, true);
                        OpenGlString.Draw(Fonts.SmallFont, $"Current frame rate: {FrameRate.ToString("0.0", culture)}fps", new Point(4, Screen.Height - 88), TextAlignment.TopLeft, Color128.White, true);
                        OpenGlString.Draw(Fonts.SmallFont, $"Total opaque faces: {VisibleObjects.OpaqueFaces.Count}", new Point(4, Screen.Height - 76), TextAlignment.TopLeft, Color128.White, true);
                        OpenGlString.Draw(Fonts.SmallFont, $"Total alpha faces: {VisibleObjects.AlphaFaces.Count}", new Point(4, Screen.Height - 64), TextAlignment.TopLeft, Color128.White, true);
                    }
                }
            }

            // finalize
            PopMatrix(MatrixMode.Projection);
            PopMatrix(MatrixMode.Modelview);
        }