public override void OnRenderFrame(RenderFrameEventArgs e) { GL.ClearColor(ClearColor); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); GL.Enable(EnableCap.DepthTest); GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); UpdateProjection(); #region Modelview GL.MatrixMode(MatrixMode.Modelview); GL.LoadIdentity(); Glu.LookAt(camera.Position, camera.Position + camera.Attitude.Direction, camera.Attitude.Up); #endregion objects.Objects["Camera Position"] = camera.Position.ToString(2); objects.Objects["Camera Direction"] = camera.Attitude.Direction.ToString(2); objects.Objects["Camera Up"] = camera.Attitude.Up.ToString(2); objects.Objects["Camera Side"] = camera.Attitude.Side.ToString(2); Renderables.Render(GetRenderInfo()); SwapBuffers(); }
/// <summary> /// Override in derived classes to render a frame. /// </summary> /// <param name="e">Contains information necessary for frame rendering.</param> /// <remarks> /// The base implementation (base.OnRenderFrame) is empty, there is no need to call it. /// </remarks> public virtual void OnRenderFrame(RenderFrameEventArgs e) { }
/// <summary> /// Enters the game loop of the GameWindow updating and rendering at the specified frequency. /// </summary> /// <param name="updates_per_second">The frequency of UpdateFrame events.</param> /// <param name="frames_per_second">The frequency of RenderFrame events.</param> public void Run(double updates_per_second, double frames_per_second) { try { if (updates_per_second < 0.0 || updates_per_second > 200.0) throw new ArgumentOutOfRangeException("updates_per_second", updates_per_second, "Parameter should be inside the range [0.0, 200.0]"); if (frames_per_second < 0.0 || frames_per_second > 200.0) throw new ArgumentOutOfRangeException("frames_per_second", frames_per_second, "Parameter should be inside the range [0.0, 200.0]"); TargetUpdateFrequency = updates_per_second; TargetRenderFrequency = frames_per_second; Stopwatch update_watch = new Stopwatch(), render_watch = new Stopwatch(); double time, next_render = 0.0, next_update = 0.0, update_time_counter = 0.0; int num_updates = 0; UpdateFrameEventArgs update_args = new UpdateFrameEventArgs(); RenderFrameEventArgs render_args = new RenderFrameEventArgs(); update_watch.Reset(); render_watch.Reset(); //double sleep_granularity; // In seconds. //GC.Collect(2); //GC.WaitForPendingFinalizers(); //GC.Collect(2); // Find the minimum granularity of the Thread.Sleep() function. // TODO: Disabled - see comment on Thread.Sleep() problems below. //update_watch.Start(); //const int test_times = 5; //for (int i = test_times; --i > 0; ) // Thread.Sleep(1); //update_watch.Stop(); //sleep_granularity = System.Math.Round(1000.0 * update_watch.Elapsed.TotalSeconds / test_times, MidpointRounding.AwayFromZero) / 1000.0; //update_watch.Reset(); // We don't want to affect the first UpdateFrame! //try //{ OnLoadInternal(EventArgs.Empty); //} //catch (Exception e) //{ // Trace.WriteLine(String.Format("OnLoad failed: {0}", e.ToString())); // return; //} //Debug.Print("Elevating priority."); //Thread.CurrentThread.Priority = ThreadPriority.AboveNormal; Debug.Print("Entering main loop."); while (!isExiting) { ProcessEvents(); // Raise UpdateFrame events time = update_watch.Elapsed.TotalSeconds; if (time > 1.0) time = 1.0; while (next_update - time <= 0.0) { next_update = next_update - time + TargetUpdatePeriod; if (next_update < -1.0) // Cap the maximum time drift, to avoid lengthy catch-up games. next_update = -1.0; update_time_counter += time; ++num_updates; update_watch.Reset(); update_watch.Start(); update_args.Time = time; OnUpdateFrameInternal(update_args); update_time = update_watch.Elapsed.TotalSeconds; if (TargetUpdateFrequency == 0.0) break; time = update_watch.Elapsed.TotalSeconds; next_update -= time; update_time_counter += time; // Allow up to 10 frames to be dropped. Prevents the application from hanging // with very high update frequencies. if (num_updates >= 10) break; } if (num_updates > 0) { update_period = update_time_counter / (double)num_updates; num_updates = 0; update_time_counter = 0.0; } // Raise RenderFrame event time = render_watch.Elapsed.TotalSeconds; if (time > 1.0) time = 1.0; double time_left = next_render - time; if (VSync == VSyncMode.Adaptive) { // Check if we have enough time for a vsync if (RenderTime > 2.0 * TargetRenderPeriod) Context.VSync = false; else Context.VSync = true; } if (time_left <= 0.0) { next_render = time_left + TargetRenderPeriod; if (next_render < -1.0) // Cap the maximum time drift, to avoid lengthy catch-up games. next_render = -1.0; render_watch.Reset(); render_watch.Start(); render_period = render_args.Time = time; render_args.ScaleFactor = RenderPeriod / UpdatePeriod; OnRenderFrameInternal(render_args); render_time = render_watch.Elapsed.TotalSeconds; } // Yield CPU time, if the Thread.Sleep() granularity allows it. // TODO: Disabled because it does not work reliably enough on all systems. // Enable vsync as a workaround. //if (AllowSleep && next_render > sleep_granularity && next_update > sleep_granularity) //{ // Thread.Sleep((int)(1000.0 * System.Math.Min(next_render - sleep_granularity, next_update - sleep_granularity))); //} } } catch (GameWindowExitException) { Trace.WriteLine("GameWindowExitException caught - exiting main loop."); } finally { Debug.Print("Restoring priority."); Thread.CurrentThread.Priority = ThreadPriority.Normal; OnUnloadInternal(EventArgs.Empty); if (this.Exists) { if (Exists) glWindow.DestroyWindow(); while (this.Exists) this.ProcessEvents(); } } }
/// <summary> /// Raises the RenderFrame event, and calls the public function. /// </summary> /// <param name="e"></param> private void OnRenderFrameInternal(RenderFrameEventArgs e) { if (!this.Exists && !this.IsExiting) { Debug.Print("WARNING: RenderFrame event raised, without a valid render window. This may indicate a programming error. Creating render window."); mode = new DisplayMode(640, 480); this.CreateWindow(mode); } if (RenderFrame != null) RenderFrame(this, e); // Call the user's override. OnRenderFrame(e); }
/// <summary> /// Called when it is time to render the next frame. Add your rendering code here. /// </summary> /// <param name="e">Contains timing information.</param> public override void OnRenderFrame(RenderFrameEventArgs e) { GL.Clear(ClearBufferMask.ColorBufferBit); if (gv != null) { //GL.Viewport((int)gv.activeWindow.X, (int)gv.activeWindow.Y, (int)gv.activeWindow.Width, (int)gv.activeWindow.Height); GL.MatrixMode(MatrixMode.Projection); GL.LoadIdentity(); Glu.Ortho2D(0, 800, gv.activeWindow.Y + 600, gv.activeWindow.Y); GL.MatrixMode(MatrixMode.Modelview); GL.LoadIdentity(); // draw all the obstacles GL.Color3(Color.Black); GL.Begin(BeginMode.Quads); foreach (deathcave_logic.gameObjects.BaseGameObject bgo in gv.obstacles) { DrawBGO(bgo); } GL.End(); // draw the shots GL.Color3(Color.YellowGreen); GL.Begin(BeginMode.Quads); foreach (deathcave_logic.gameObjects.BaseGameObject bgo in gv.projectiles) { DrawBGO(bgo); } GL.End(); // draw explosions GL.Color3(Color.Red); GL.Begin(BeginMode.Quads); foreach (deathcave_logic.gameObjects.BaseGameObject bgo in gv.effects) { DrawBGO(bgo); } GL.End(); //draw the enemies GL.Begin(BeginMode.Quads); foreach (deathcave_logic.gameObjects.BaseGameObject bgo in gv.enemies) { switch (bgo.ObjectType) { case GameObjectEnum.EnemyDropper: GL.Color3(Color.Plum); break; case GameObjectEnum.EnemyShooter: GL.Color3(Color.SeaShell); break; case GameObjectEnum.EnemySwooper: GL.Color3(Color.BlanchedAlmond); break; } DrawBGO(bgo); } GL.End(); // draw the ship if (this.gv.safeTimer < 0.0f) GL.Color3(Color.Blue); else GL.Color3(Color.Yellow); GL.Begin(BeginMode.Quads); DrawBGO(gv.ship); GL.End(); } SwapBuffers(); }