From 10dd5d7205aa2fad77cedb4b950dd82075eddb8b Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 28 Sep 2023 10:51:08 -0700 Subject: [PATCH] flashing now looks consistent at high frame rates --- .efrocachemap | 40 +++++++++---------- CHANGELOG.md | 4 +- src/assets/ba_data/python/baenv.py | 2 +- src/ballistica/base/graphics/graphics.cc | 24 +++++++++-- src/ballistica/base/graphics/graphics.h | 4 +- .../base/graphics/support/frame_def.h | 18 +++++++-- src/ballistica/scene_v1/node/prop_node.cc | 4 +- src/ballistica/scene_v1/node/spaz_node.cc | 4 +- src/ballistica/shared/ballistica.cc | 2 +- 9 files changed, 67 insertions(+), 35 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 6709264b..c1e1e508 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -4056,26 +4056,26 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "ffaf93fda978f8d8855b1478215d083f", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "eb15777efa005cd1918dfe72bd251a2e", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "b0f9fa5d756729406cd033f408a5ba55", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "a323d1f530b6f84df1f3124cb9d7088b", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "e07abf32475dc72cc60bb29796dbc306", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "3d4a6f06eb9a714c9fe6d55cbe42262d", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "b74e814b14e38ab22bea0e5854086636", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "dc8de989859d88a10f138d512173292d", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "047a4ea01c6431dc49a761d2d06e9d90", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "9a5cd21b636ee436d5c05321a9a99f2b", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "4e9c476e0796d54dac0bc6571bdb1cae", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "64f23ab5c54d8eaaa0f2cc03dc3107ad", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "91bf11303d5c1d1369f98a1b972ee932", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "6629cb52ad1bbf62e25bf7f872788542", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "66dde4d3bec81f59344a4acef80ec465", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "75e7e50b7b35ab91d46c3692cb7e62d3", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "0f78c8a79e099e65b14dad33287ce513", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "dd62b63f16f7e3b0a0df24a0553ea993", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "e6932e574050c81926b7d78b6a8c30e9", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "e8383e509d1827e796af581eb6920458", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "879f9ae6e9feb73e78f485b651cd34c7", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "ff1fa0221ac83f4d531134b9a9a87356", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "4d4fd7114044126319142a4668456bd5", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "2d7d1d66d4d39aa312b973118b970851", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "2b42e72406fb0c54bfd5c3dcdeca0a89", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "977c9fc76d955ce30c709d97127d2b3d", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "15d20411f5c80701a78e08d5bf832e94", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "dce80ee691257accb0a87f41ff4f673e", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "a84e2b62b91d6cf6d9ec20b28af5c629", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "477bf924c8d9f9e2d646dee4006ce1d9", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "79b4e2cd534ec0adec870d54c47e4e17", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "4e2caa995f9d806124c4d715105606a3", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "4b7878086aa663c03679d568109d0dc6", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "457020313456fd2e255bd25588fc87d8", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "dec55597731654d412ff2756c9e574c6", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "0a0c061db51c8bfed9eabd085e3978a7", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "1724f00d6acffd249a01b85482ae322c", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "5626611d504dd205ea318d720a134816", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "ea6804ac87fe463666deeeb6bc1a2dc1", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "bfaf973230af195bfd9ec18cff3db17a", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "f3d305e647a7f77dd70a48f615cfd750", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "931ce8eab9859d20ad86c47d196ba62c", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "f3d305e647a7f77dd70a48f615cfd750", diff --git a/CHANGELOG.md b/CHANGELOG.md index 05fca41e..4f05b3a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21391, api 8, 2023-09-28) +### 1.7.28 (build 21393, api 8, 2023-09-28) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years @@ -27,6 +27,8 @@ - Debug speed adjustments are now Ctrl-plus or Ctrl-minus instead of just plus or minus. This makes these safer in case we want to enable them in regular builds at some point. +- Flashing things in the game (powerups about to disappear, etc.) now flash at a + consistent rate even on high frame rate setups. - Renamed Console to DevConsole, and added an option under advanced settings to always show a 'dev' button onscreen which can be used to toggle it. The backtick key still works also for anyone with a keyboard. I plan to add more diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 6ec72c2d..0248a106 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21391 +TARGET_BALLISTICA_BUILD = 21393 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/ballistica/base/graphics/graphics.cc b/src/ballistica/base/graphics/graphics.cc index b35df413..818653d3 100644 --- a/src/ballistica/base/graphics/graphics.cc +++ b/src/ballistica/base/graphics/graphics.cc @@ -1122,10 +1122,27 @@ void Graphics::BuildAndPushFrameDef() { // Store how much time this frame_def represents. auto display_time_microsecs = g_base->logic->display_time_microsecs(); - millisecs_t elapsed_microsecs = std::min( - millisecs_t{50000}, display_time_microsecs - last_create_frame_def_time_); + // Clamp a frame-def's elapsed time to 1/10th of a second even if it has + // been longer than that since the last. Don't want things like + // motion-blur to get out of control. + millisecs_t elapsed_microsecs = + std::min(microsecs_t{100000}, + display_time_microsecs - last_create_frame_def_time_); last_create_frame_def_time_ = display_time_microsecs; + frame_def_count_++; + + // Update our filtered frame-number (clamped at 60hz so it can be used + // for drawing without looking wonky at high frame rates). + if (display_time_microsecs >= next_frame_number_filtered_increment_time_) { + frame_def_count_filtered_ += 1; + // Schedule the next increment for 1/60th of a second after the last (or + // now, whichever is later). + next_frame_number_filtered_increment_time_ = + std::max(display_time_microsecs, + next_frame_number_filtered_increment_time_ + 1000000 / 60); + } + // This probably should not be here. Though I guess we get the most // up-to-date values possible this way. But it should probably live in // g_input. @@ -1136,7 +1153,8 @@ void Graphics::BuildAndPushFrameDef() { frame_def->set_display_time_microsecs( g_base->logic->display_time_microsecs()); frame_def->set_display_time_elapsed_microsecs(elapsed_microsecs); - frame_def->set_frame_number(frame_def_count_++); + frame_def->set_frame_number(frame_def_count_); + frame_def->set_frame_number_filtered(frame_def_count_filtered_); if (!internal_components_inited_) { InitInternalComponents(frame_def); diff --git a/src/ballistica/base/graphics/graphics.h b/src/ballistica/base/graphics/graphics.h index fa2b28f0..199b4f7d 100644 --- a/src/ballistica/base/graphics/graphics.h +++ b/src/ballistica/base/graphics/graphics.h @@ -443,7 +443,9 @@ class Graphics { float shadow_upper_bottom_{30.0f}; float shadow_upper_top_{40.0f}; millisecs_t last_cursor_visibility_event_time_{}; - int64_t frame_def_count_{1}; + microsecs_t next_frame_number_filtered_increment_time_{}; + int64_t frame_def_count_{}; + int64_t frame_def_count_filtered_{}; microsecs_t last_suppress_gyro_time_{}; Object::Ref fade_end_call_; }; diff --git a/src/ballistica/base/graphics/support/frame_def.h b/src/ballistica/base/graphics/support/frame_def.h index 27797652..77999caa 100644 --- a/src/ballistica/base/graphics/support/frame_def.h +++ b/src/ballistica/base/graphics/support/frame_def.h @@ -47,10 +47,18 @@ class FrameDef { return static_cast(app_time_microsecs_) / 1000000.0; } - // A number incremented for each frame renderered. Try to avoid using this - // for drawing flashes/etc. since framerates can vary a lot these days; a - // 30hz flash will look a lot different than a 240hz one. - auto frame_number() const -> int64_t { return frame_number_; } + // A number incremented for each frame renderered. Note that graphics code + // should not plug this directly into things like flash calculations since + // frame-rates will vary a lot these days. A 30hz flash will look a lot + // different than a 240hz flash. Use frame_number_filtered() for such + // purposes. + auto frame_number() const { return frame_number_; } + + // A number incremented for each frame rendered, but a maximum of 60 times + // per second. Code for drawing flashes or other exact effects should use + // this value instead of regular frame_number so that things don't turn + // muddy at extremely high frame rates. + auto frame_number_filtered() const { return frame_number_filtered_; } // Returns the display-time this frame-def was created at (tries to match // real time but is incremented more smoothly so is better for drawing @@ -134,6 +142,7 @@ class FrameDef { display_time_microsecs_ = val; } void set_frame_number(int64_t val) { frame_number_ = val; } + void set_frame_number_filtered(int64_t val) { frame_number_filtered_ = val; } auto overlay_flat_pass() const -> RenderPass* { return overlay_flat_pass_.get(); @@ -234,6 +243,7 @@ class FrameDef { microsecs_t display_time_microsecs_{}; microsecs_t display_time_elapsed_microsecs_{}; int64_t frame_number_{}; + int64_t frame_number_filtered_{}; Vector3f shadow_offset_{0.0f, 0.0f, 0.0f}; Vector2f shadow_scale_{1.0f, 1.0f}; Vector3f tint_{1.0f, 1.0f, 1.0f}; diff --git a/src/ballistica/scene_v1/node/prop_node.cc b/src/ballistica/scene_v1/node/prop_node.cc index 6b8539e8..4f48492c 100644 --- a/src/ballistica/scene_v1/node/prop_node.cc +++ b/src/ballistica/scene_v1/node/prop_node.cc @@ -114,7 +114,7 @@ void PropNode::Draw(base::FrameDef* frame_def) { c.SetReflectionScale(reflection_scale_r_, reflection_scale_g_, reflection_scale_b_); } - if (flashing_ && frame_def->frame_number() % 10 < 5) { + if (flashing_ && frame_def->frame_number_filtered() % 10 < 5) { c.SetColor(1.2f, 1.2f, 1.2f); } { @@ -185,7 +185,7 @@ void PropNode::Draw(base::FrameDef* frame_def) { c2.SetPremultiplied(true); c2.SetTexture(color_texture_.Exists() ? color_texture_->texture_data() : nullptr); - if (flashing_ && frame_def->frame_number() % 10 < 5) { + if (flashing_ && frame_def->frame_number_filtered() % 10 < 5) { c2.SetColor(0.026f * s_density, 0.026f * s_density, 0.026f * s_density, 0.0f); } else { diff --git a/src/ballistica/scene_v1/node/spaz_node.cc b/src/ballistica/scene_v1/node/spaz_node.cc index 91e9a276..2beab1a9 100644 --- a/src/ballistica/scene_v1/node/spaz_node.cc +++ b/src/ballistica/scene_v1/node/spaz_node.cc @@ -4672,7 +4672,7 @@ void SpazNode::Draw(base::FrameDef* frame_def) { #endif // BA_OSTYPE_MACOS millisecs_t scenetime = scene()->time(); - int64_t render_frame_count = frame_def->frame_number(); + int64_t render_frame_count = frame_def->frame_number_filtered(); auto* beauty_pass = frame_def->beauty_pass(); float death_fade = 1.0f; @@ -4704,7 +4704,7 @@ void SpazNode::Draw(base::FrameDef* frame_def) { // Invincible! flash white. if (invincible_) { - if (frame_def->frame_number() % 6 < 3) { + if (frame_def->frame_number_filtered() % 6 < 3) { add_color[0] = 0.12f; add_color[1] = 0.22f; add_color[2] = 0.0f; diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 73c4119a..9a2b58c5 100644 --- a/src/ballistica/shared/ballistica.cc +++ b/src/ballistica/shared/ballistica.cc @@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int { namespace ballistica { // These are set automatically via script; don't modify them here. -const int kEngineBuildNumber = 21391; +const int kEngineBuildNumber = 21393; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8;