diff options
| -rw-r--r-- | src/Render.cpp | 23 | ||||
| -rw-r--r-- | src/Render.hpp | 2 | ||||
| -rw-r--r-- | src/Time.cpp | 5 | ||||
| -rw-r--r-- | src/Time.hpp | 7 |
4 files changed, 36 insertions, 1 deletions
diff --git a/src/Render.cpp b/src/Render.cpp index 2b16ed0..caebc29 100644 --- a/src/Render.cpp +++ b/src/Render.cpp @@ -7,6 +7,9 @@ #include "GFX/Image/PPMParser.hpp" #include "GFX/Shading/Program.hpp" #include "Math/MVP.hpp" +#include <thread> + +#define FPS_LIMIT 30 namespace MC { @@ -36,12 +39,22 @@ void Render::run() { glFrontFace(GL_CCW); glCullFace(GL_BACK); + Time render_time{}; + while (!m_window.should_close()) { Scene scene = m_control->wait_for_render_data(); + render_time.start_frame(); m_window.start_render(); render_scene(scene, texture); + render_time.end_frame(); + wait_until_next_frame_start(render_time.delta_raw()); + + // This signal has to be the last thing in the loop, + // otherwise the logic thread could be blocked during + // it's `wait_for_render_finish` call. + // Still weird though, maybe there's a better way? m_control->finish_render(); } } @@ -102,4 +115,14 @@ void Render::setup_gl() { } } +void Render::wait_until_next_frame_start(Real spent_time_budget) const { + constexpr Real total_frame_time_budget = 1.0 / FPS_LIMIT; + Real remaining_time_budget = total_frame_time_budget - spent_time_budget; + + if (remaining_time_budget > 0) { + auto frame_end = Time::now() + TO(U64, remaining_time_budget * 1000); + while (Time::now() < frame_end) std::this_thread::yield(); + } +} + } diff --git a/src/Render.hpp b/src/Render.hpp index 09c6fee..6670858 100644 --- a/src/Render.hpp +++ b/src/Render.hpp @@ -80,6 +80,8 @@ private: void render_scene(Scene const& actions, GFX::Texture const& texture) const; static void setup_gl(); + void wait_until_next_frame_start(Real spent_time_budget) const; + GFX::Resources m_resources; GFX::Window& m_window; std::shared_ptr<Control> m_control; diff --git a/src/Time.cpp b/src/Time.cpp index 1953fed..a9608cc 100644 --- a/src/Time.cpp +++ b/src/Time.cpp @@ -12,7 +12,6 @@ void Time::start_frame() { void Time::end_frame() { auto frame_end = now(); m_delta = TO(Real, frame_end - m_current_frame_start) / 1000.0; - m_delta = std::clamp(m_delta, delta_min, delta_max); m_total_frames++; } @@ -26,6 +25,10 @@ Time::Tick Time::tick() const { } Real Time::delta() const { + return std::clamp(m_delta, delta_min, delta_max); +} + +Real Time::delta_raw() const { return m_delta; } diff --git a/src/Time.hpp b/src/Time.hpp index 64ab4a2..62e2809 100644 --- a/src/Time.hpp +++ b/src/Time.hpp @@ -7,8 +7,10 @@ namespace MC { class Time { public: + // TODO: Document exact units of types. using Timestamp = U64; using Tick = U64; + // TODO: Create `Time::Duration` type. Time() = default; @@ -23,7 +25,12 @@ public: // This is the same as total_frames(), but is more descriptive, sometimes. // :) PURE Tick tick() const; + // The time in seconds that has passed since the last frame. + // This is always a value between `0.001` and `0.1`. PURE Real delta() const; + // The time in seconds that has passed since the last frame. + // Unlike `delta()`, this value is not clamped, and can be any positive value. + PURE Real delta_raw() const; PURE Timestamp frame_start() const; |
