From 7b98255626876870cc921693fde5c0ef384a604a Mon Sep 17 00:00:00 2001 From: "Stefanos A." Date: Tue, 14 Jan 2014 13:27:09 +0100 Subject: [PATCH] [Examples] Improved timing display GameWindowStates will now display the average fps and draw three moving boxes based on different timing methods. If the timing implementation in OpenTK is working correctly, all three boxes should be moving at the same speed. --- .../Examples/OpenTK/Test/GameWindowStates.cs | 145 +++++++++++++++--- 1 file changed, 122 insertions(+), 23 deletions(-) diff --git a/Source/Examples/OpenTK/Test/GameWindowStates.cs b/Source/Examples/OpenTK/Test/GameWindowStates.cs index 10ae3141..f5cbcfea 100644 --- a/Source/Examples/OpenTK/Test/GameWindowStates.cs +++ b/Source/Examples/OpenTK/Test/GameWindowStates.cs @@ -25,9 +25,23 @@ namespace Examples.Tests int texture; bool mouse_in_window = false; bool viewport_changed = true; + + // time drift Stopwatch watch = new Stopwatch(); double update_time, render_time; + // timing information + double timestamp; + int update_count; + int update_fps; + int render_count; + int render_fps; + + // position of moving objects on screen + double variable_update_timestep_pos = -1; + double variable_refresh_timestep_pos = -1; + double fixed_update_timestep_pos = -1; + public GameWindowStates() : base(800, 600, GraphicsMode.Default) { @@ -35,10 +49,10 @@ namespace Examples.Tests Keyboard.KeyRepeat = true; KeyDown += KeyDownHandler; KeyPress += KeyPressHandler; - + MouseEnter += delegate { mouse_in_window = true; }; MouseLeave += delegate { mouse_in_window = false; }; - + Mouse.Move += MouseMoveHandler; Mouse.ButtonDown += MouseButtonHandler; Mouse.ButtonUp += MouseButtonHandler; @@ -110,7 +124,7 @@ namespace Examples.Tests { return val > max ? max : val < min ? min : val; } - + static float DrawString(Graphics gfx, string str, int line) { return DrawString(gfx, str, line, 0); @@ -217,6 +231,8 @@ namespace Examples.Tests { double clock_time = watch.Elapsed.TotalSeconds; update_time += e.Time; + timestamp += e.Time; + update_count++; using (Graphics gfx = Graphics.FromImage(TextBitmap)) { @@ -247,22 +263,47 @@ namespace Examples.Tests // Timing information line++; DrawString(gfx, "Timing:", line++); - DrawString(gfx, String.Format("Frequency: update ({0:f2}/{1:f2}); render ({2:f2}/{3:f2})", - UpdateFrequency, TargetUpdateFrequency, RenderFrequency, TargetRenderFrequency), line++); - DrawString(gfx, String.Format("Period: update ({0:f4}/{1:f4}); render ({2:f4}/{3:f4})", - UpdatePeriod, TargetUpdatePeriod, RenderPeriod, TargetRenderPeriod), line++); + DrawString(gfx, + String.Format("Frequency: update {4} ({0:f2}/{1:f2}); render {5} ({2:f2}/{3:f2})", + UpdateFrequency, TargetUpdateFrequency, + RenderFrequency, TargetRenderFrequency, + update_fps, render_fps), + line++); + DrawString(gfx, + String.Format("Period: update {4:N4} ({0:f4}/{1:f4}); render {5:N4} ({2:f4}/{3:f4})", + UpdatePeriod, TargetUpdatePeriod, + RenderPeriod, TargetRenderPeriod, + 1.0 / update_fps, 1.0 / render_fps), + line++); DrawString(gfx, String.Format("Time: update {0:f4}; render {1:f4}", - UpdateTime, RenderTime), line++); + UpdateTime, RenderTime), line++); DrawString(gfx, String.Format("Drift: clock {0:f4}; update {1:f4}; render {2:f4}", clock_time, clock_time - update_time, clock_time - render_time), line++); DrawString(gfx, String.Format("Text: {0}", TypedText.ToString()), line++); + if (timestamp >= 1) + { + timestamp -= 1; + update_fps = update_count; + render_fps = render_count; + update_count = 0; + render_count = 0; + + } + // Input information line = DrawKeyboards(gfx, line); line = DrawMice(gfx, line); line = DrawJoysticks(gfx, line); line = DrawLegacyJoysticks(gfx, Joysticks, line); } + + fixed_update_timestep_pos += TargetUpdatePeriod; + variable_update_timestep_pos += e.Time; + if (fixed_update_timestep_pos >= 1) + fixed_update_timestep_pos -= 2; + if (variable_update_timestep_pos >= 1) + variable_update_timestep_pos -= 2; } int DrawJoysticks(Graphics gfx, int line) @@ -323,7 +364,31 @@ namespace Examples.Tests protected override void OnRenderFrame(FrameEventArgs e) { render_time += e.Time; + render_count++; + GL.Clear(ClearBufferMask.ColorBufferBit); + + if (viewport_changed) + { + viewport_changed = false; + GL.Viewport(0, 0, Width, Height); + } + + DrawText(); + + DrawMovingObjects(); + + variable_refresh_timestep_pos += e.Time; + if (variable_refresh_timestep_pos >= 1) + variable_refresh_timestep_pos -= 2; + + SwapBuffers(); + } + + // Uploads our text Bitmap to an OpenGL texture + // and displays is to screen. + private void DrawText() + { System.Drawing.Imaging.BitmapData data = TextBitmap.LockBits( new System.Drawing.Rectangle(0, 0, TextBitmap.Width, TextBitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); @@ -331,29 +396,63 @@ namespace Examples.Tests PixelType.UnsignedByte, data.Scan0); TextBitmap.UnlockBits(data); - if (viewport_changed) - { - viewport_changed = false; - - GL.Viewport(0, 0, Width, Height); - - Matrix4 ortho_projection = Matrix4.CreateOrthographicOffCenter(0, Width, Height, 0, -1, 1); - GL.MatrixMode(MatrixMode.Projection); - GL.LoadMatrix(ref ortho_projection); - } - - GL.Clear(ClearBufferMask.ColorBufferBit); + Matrix4 text_projection = Matrix4.CreateOrthographicOffCenter(0, Width, Height, 0, -1, 1); + GL.MatrixMode(MatrixMode.Projection); + GL.LoadMatrix(ref text_projection); + GL.MatrixMode(MatrixMode.Modelview); + GL.LoadIdentity(); + GL.Color4(Color4.White); + GL.Enable(EnableCap.Texture2D); GL.Begin(PrimitiveType.Quads); - GL.TexCoord2(0, 0); GL.Vertex2(0, 0); GL.TexCoord2(1, 0); GL.Vertex2(TextBitmap.Width, 0); GL.TexCoord2(1, 1); GL.Vertex2(TextBitmap.Width, TextBitmap.Height); GL.TexCoord2(0, 1); GL.Vertex2(0, TextBitmap.Height); - GL.End(); + GL.Disable(EnableCap.Texture2D); + } - SwapBuffers(); + // Draws three moving objects, using three different timing methods: + // 1. fixed framerate based on TargetUpdatePeriod + // 2. variable framerate based on UpdateFrame e.Time + // 3. variable framerate based on RenderFrame e.Time + // If the timing implementation is correct, all three objects + // should be moving at the same speed, regardless of the current + // UpdatePeriod and RenderPeriod. + void DrawMovingObjects() + { + Matrix4 thing_projection = Matrix4.CreateOrthographic(2, 2, -1, 1); + GL.MatrixMode(MatrixMode.Projection); + GL.LoadMatrix(ref thing_projection); + + GL.MatrixMode(MatrixMode.Modelview); + GL.LoadIdentity(); + GL.Translate(fixed_update_timestep_pos, -0.2, 0); + GL.Color4(Color4.Red); + DrawRectangle(); + + GL.MatrixMode(MatrixMode.Modelview); + GL.LoadIdentity(); + GL.Translate(variable_update_timestep_pos, -0.4, 0); + GL.Color4(Color4.DarkGoldenrod); + DrawRectangle(); + + GL.MatrixMode(MatrixMode.Modelview); + GL.LoadIdentity(); + GL.Translate(variable_refresh_timestep_pos, -0.8, 0); + GL.Color4(Color4.DarkGreen); + DrawRectangle(); + } + + private void DrawRectangle() + { + GL.Begin(PrimitiveType.Quads); + GL.Vertex2(-0.05, -0.05); + GL.Vertex2(+0.05, -0.05); + GL.Vertex2(+0.05, +0.05); + GL.Vertex2(-0.05, +0.05); + GL.End(); } public static void Main()