From 621e5beaef8f99be281b7bffe7c0ef762ca1afe9 Mon Sep 17 00:00:00 2001 From: Mosch0512 Date: Sat, 7 Feb 2026 02:29:20 +0100 Subject: [PATCH 1/7] Add $fpscounter chat command to toggle debug info overlay RenderDebugInfo (FPS, mouse position, camera angles) is now: - Always on in Debug builds - Off by default in Release builds, toggle with $fpscounter on/off The $fpscounter command is checked before the $fps prefix to avoid a crash from trying to parse "ounter on" as a float. --- src/source/Scenes/SceneManager.cpp | 14 ++++++++++++-- src/source/Utilities/Log/muConsoleDebug.cpp | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/source/Scenes/SceneManager.cpp b/src/source/Scenes/SceneManager.cpp index 43e64a85c..4ac159c4b 100644 --- a/src/source/Scenes/SceneManager.cpp +++ b/src/source/Scenes/SceneManager.cpp @@ -58,6 +58,15 @@ extern bool Destroy; extern double WorldTime; extern float FPS_ANIMATION_FACTOR; +static bool g_bShowDebugInfo = +#ifdef _DEBUG + true; +#else + false; +#endif + +void SetShowDebugInfo(bool enabled) { g_bShowDebugInfo = enabled; } + void SetTargetFps(double targetFps) { if (IsVSyncEnabled() && targetFps >= GetFPSLimit()) @@ -298,7 +307,9 @@ static bool RenderCurrentScene(HDC hDC) */ static void RenderDebugInfo() { -#if defined(_DEBUG) || defined(LDS_FOR_DEVELOPMENT_TESTMODE) || defined(LDS_UNFIXED_FIXEDFRAME_FORDEBUG) + if (!g_bShowDebugInfo) + return; + BeginBitmap(); wchar_t szDebugText[128]; swprintf(szDebugText, L"FPS: %.1f Vsync: %d CPU: %.1f%%", FPS_AVG, IsVSyncEnabled(), CPU_AVG); @@ -314,7 +325,6 @@ static void RenderDebugInfo() g_pRenderText->RenderText(10, 46, szCamera3D); g_pRenderText->SetFont(g_hFont); EndBitmap(); -#endif // defined(_DEBUG) || defined(LDS_FOR_DEVELOPMENT_TESTMODE) || defined(LDS_UNFIXED_FIXEDFRAME_FORDEBUG) } /** diff --git a/src/source/Utilities/Log/muConsoleDebug.cpp b/src/source/Utilities/Log/muConsoleDebug.cpp index 4582d3a24..df642f341 100644 --- a/src/source/Utilities/Log/muConsoleDebug.cpp +++ b/src/source/Utilities/Log/muConsoleDebug.cpp @@ -79,6 +79,20 @@ void CmuConsoleDebug::UpdateMainScene() bool CmuConsoleDebug::CheckCommand(const std::wstring& strCommand) { + if (strCommand.compare(L"$fpscounter on") == 0) + { + extern void SetShowDebugInfo(bool); + SetShowDebugInfo(true); + return true; + } + + if (strCommand.compare(L"$fpscounter off") == 0) + { + extern void SetShowDebugInfo(bool); + SetShowDebugInfo(false); + return true; + } + if (strCommand.compare(0, 4, L"$fps") == 0) { auto fps_str = strCommand.substr(5); From 1c57c1d81cf2248777878a6e341b03b571cb1dc2 Mon Sep 17 00:00:00 2001 From: Mosch0512 Date: Sat, 7 Feb 2026 03:20:29 +0100 Subject: [PATCH 2/7] Add detailed FPS statistics and frame time graph to debug overlay Show avg FPS, max FPS, 1% low, 0.1% low, frame time in ms. Render a color-coded frame time bar graph (green/yellow/red) with a 60fps reference line. --- src/source/Scenes/SceneManager.cpp | 173 +++++++++++++++++++++++++++-- 1 file changed, 162 insertions(+), 11 deletions(-) diff --git a/src/source/Scenes/SceneManager.cpp b/src/source/Scenes/SceneManager.cpp index 4ac159c4b..ce90cd716 100644 --- a/src/source/Scenes/SceneManager.cpp +++ b/src/source/Scenes/SceneManager.cpp @@ -4,6 +4,7 @@ #include "stdafx.h" #include +#include #include "SceneManager.h" //============================================================================= @@ -67,6 +68,66 @@ static bool g_bShowDebugInfo = void SetShowDebugInfo(bool enabled) { g_bShowDebugInfo = enabled; } +//============================================================================= +// Frame Statistics Tracker +//============================================================================= + +static constexpr int FRAME_HISTORY_SIZE = 300; // ~5 seconds at 60fps +static float s_frameTimesMs[FRAME_HISTORY_SIZE] = {}; +static int s_frameIndex = 0; +static int s_frameCount = 0; +static double s_lastFrameTime = 0.0; +static double s_highestFps = 0.0; + +// Percentile stats (updated periodically) +static float s_avgFps = 0.0f; +static float s_onePercentLow = 0.0f; +static float s_pointOnePercentLow = 0.0f; +static double s_lastStatsUpdate = 0.0; + +static void UpdateFrameStats() +{ + double now = WorldTime; + if (s_lastFrameTime > 0.0) + { + double dt = now - s_lastFrameTime; + if (dt < 0.5) dt = 0.5; // clamp to 2000fps max + s_frameTimesMs[s_frameIndex] = static_cast(dt); + s_frameIndex = (s_frameIndex + 1) % FRAME_HISTORY_SIZE; + if (s_frameCount < FRAME_HISTORY_SIZE) s_frameCount++; + } + s_lastFrameTime = now; + + if (FPS_AVG > s_highestFps) s_highestFps = FPS_AVG; + + // Update percentile stats every 500ms + if (now - s_lastStatsUpdate > 500.0 && s_frameCount > 10) + { + s_lastStatsUpdate = now; + + // Copy and sort frame times (descending = slowest first) + static float sorted[FRAME_HISTORY_SIZE]; + memcpy(sorted, s_frameTimesMs, sizeof(float) * s_frameCount); + std::sort(sorted, sorted + s_frameCount, std::greater()); + + // Average + float sum = 0.0f; + for (int i = 0; i < s_frameCount; i++) sum += sorted[i]; + float avgMs = sum / s_frameCount; + s_avgFps = (avgMs > 0.0f) ? 1000.0f / avgMs : 0.0f; + + // 1% low: average of the slowest 1% of frames + int onePercCount = std::max(1, s_frameCount / 100); + float onePercSum = 0.0f; + for (int i = 0; i < onePercCount; i++) onePercSum += sorted[i]; + float onePercAvgMs = onePercSum / onePercCount; + s_onePercentLow = (onePercAvgMs > 0.0f) ? 1000.0f / onePercAvgMs : 0.0f; + + // 0.1% low: the single slowest frame in the window + s_pointOnePercentLow = (sorted[0] > 0.0f) ? 1000.0f / sorted[0] : 0.0f; + } +} + void SetTargetFps(double targetFps) { if (IsVSyncEnabled() && targetFps >= GetFPSLimit()) @@ -301,28 +362,118 @@ static bool RenderCurrentScene(HDC hDC) } /** - * @brief Renders debug information overlay in development builds. + * @brief Renders a frame time graph using raw OpenGL quads. + * + * Draws a bar chart of recent frame times inside BeginBitmap's 2D ortho projection. + * Coordinates are in virtual 640x480 space, converted to window pixels. + */ +static void RenderFrameGraph(float graphX, float graphY, float graphW, float graphH) +{ + if (s_frameCount < 2) + return; + + // Convert virtual 640x480 coords to actual window pixels + float gx = graphX * (float)WindowWidth / 640.f; + float gy = graphY * (float)WindowHeight / 480.f; + float gw = graphW * (float)WindowWidth / 640.f; + float gh = graphH * (float)WindowHeight / 480.f; + + // Flip Y for OpenGL (origin bottom-left) + float glBottom = (float)WindowHeight - gy - gh; + float glTop = (float)WindowHeight - gy; + + // Background + glDisable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glColor4f(0.0f, 0.0f, 0.0f, 0.5f); + glBegin(GL_QUADS); + glVertex2f(gx, glBottom); + glVertex2f(gx + gw, glBottom); + glVertex2f(gx + gw, glTop); + glVertex2f(gx, glTop); + glEnd(); + + // Target line at 16.67ms (60fps) + float maxMs = 33.3f; // graph scales to 33.3ms (30fps) max + float target60 = 16.67f / maxMs; + float lineY = glBottom + target60 * gh; + glColor4f(0.3f, 0.8f, 0.3f, 0.5f); + glBegin(GL_LINES); + glVertex2f(gx, lineY); + glVertex2f(gx + gw, lineY); + glEnd(); + + // Frame bars + float barW = gw / FRAME_HISTORY_SIZE; + int oldest = (s_frameCount < FRAME_HISTORY_SIZE) ? 0 : s_frameIndex; + + for (int i = 0; i < s_frameCount; i++) + { + int idx = (oldest + i) % FRAME_HISTORY_SIZE; + float ms = s_frameTimesMs[idx]; + float norm = std::min(ms / maxMs, 1.0f); + float barH = norm * gh; + + // Color: green < 16ms, yellow < 25ms, red >= 25ms + if (ms < 16.67f) + glColor4f(0.2f, 0.9f, 0.2f, 0.8f); + else if (ms < 25.0f) + glColor4f(0.9f, 0.9f, 0.2f, 0.8f); + else + glColor4f(0.9f, 0.2f, 0.2f, 0.8f); + + float bx = gx + i * barW; + glBegin(GL_QUADS); + glVertex2f(bx, glBottom); + glVertex2f(bx + barW, glBottom); + glVertex2f(bx + barW, glBottom + barH); + glVertex2f(bx, glBottom + barH); + glEnd(); + } + + glEnable(GL_TEXTURE_2D); +} + +/** + * @brief Renders debug information overlay. * - * Shows FPS, mouse position, and camera info on screen. + * Shows FPS stats, percentile lows, mouse position, camera info, and frame time graph. */ static void RenderDebugInfo() { if (!g_bShowDebugInfo) return; + UpdateFrameStats(); + BeginBitmap(); - wchar_t szDebugText[128]; - swprintf(szDebugText, L"FPS: %.1f Vsync: %d CPU: %.1f%%", FPS_AVG, IsVSyncEnabled(), CPU_AVG); - wchar_t szMousePos[128]; - swprintf(szMousePos, L"MousePos : %d %d %d", MouseX, MouseY, MouseLButtonPush); - wchar_t szCamera3D[128]; - swprintf(szCamera3D, L"Camera3D : %.1f %.1f:%.1f:%.1f", CameraFOV, CameraAngle[0], CameraAngle[1], CameraAngle[2]); + + wchar_t szLine[128]; g_pRenderText->SetFont(g_hFontBold); g_pRenderText->SetBgColor(0, 0, 0, 100); g_pRenderText->SetTextColor(255, 255, 255, 200); - g_pRenderText->RenderText(10, 26, szDebugText); - g_pRenderText->RenderText(10, 36, szMousePos); - g_pRenderText->RenderText(10, 46, szCamera3D); + + int y = 26; + swprintf(szLine, L"FPS: %.1f Avg: %.1f Max: %.1f Vsync: %d CPU: %.1f%%", + FPS_AVG, s_avgFps, s_highestFps, IsVSyncEnabled(), CPU_AVG); + g_pRenderText->RenderText(10, y, szLine); y += 10; + + swprintf(szLine, L"1%% Low: %.1f 0.1%% Low: %.1f Frame: %.2fms", + s_onePercentLow, s_pointOnePercentLow, + (FPS_AVG > 0.0) ? 1000.0 / FPS_AVG : 0.0); + g_pRenderText->RenderText(10, y, szLine); y += 10; + + swprintf(szLine, L"MousePos: %d %d %d", MouseX, MouseY, MouseLButtonPush); + g_pRenderText->RenderText(10, y, szLine); y += 10; + + swprintf(szLine, L"Camera3D: %.1f %.1f:%.1f:%.1f", CameraFOV, CameraAngle[0], CameraAngle[1], CameraAngle[2]); + g_pRenderText->RenderText(10, y, szLine); y += 10; + + // Frame time graph below text + RenderFrameGraph(10.0f, (float)(y + 2), 200.0f, 40.0f); + g_pRenderText->SetFont(g_hFont); EndBitmap(); } From 67640ee56d9a7ced349aa4d306f456cca183ac4d Mon Sep 17 00:00:00 2001 From: Mosch0512 Date: Sat, 7 Feb 2026 03:30:00 +0100 Subject: [PATCH 3/7] Reset frame stats counters when toggling vsync --- src/source/Scenes/SceneManager.cpp | 13 +++++++++++++ src/source/Utilities/Log/muConsoleDebug.cpp | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/src/source/Scenes/SceneManager.cpp b/src/source/Scenes/SceneManager.cpp index ce90cd716..0c563f342 100644 --- a/src/source/Scenes/SceneManager.cpp +++ b/src/source/Scenes/SceneManager.cpp @@ -85,6 +85,19 @@ static float s_onePercentLow = 0.0f; static float s_pointOnePercentLow = 0.0f; static double s_lastStatsUpdate = 0.0; +void ResetFrameStats() +{ + memset(s_frameTimesMs, 0, sizeof(s_frameTimesMs)); + s_frameIndex = 0; + s_frameCount = 0; + s_lastFrameTime = 0.0; + s_highestFps = 0.0; + s_avgFps = 0.0f; + s_onePercentLow = 0.0f; + s_pointOnePercentLow = 0.0f; + s_lastStatsUpdate = 0.0; +} + static void UpdateFrameStats() { double now = WorldTime; diff --git a/src/source/Utilities/Log/muConsoleDebug.cpp b/src/source/Utilities/Log/muConsoleDebug.cpp index df642f341..32c01ca7f 100644 --- a/src/source/Utilities/Log/muConsoleDebug.cpp +++ b/src/source/Utilities/Log/muConsoleDebug.cpp @@ -105,12 +105,16 @@ bool CmuConsoleDebug::CheckCommand(const std::wstring& strCommand) { EnableVSync(); SetTargetFps(-1); // unlimited + extern void ResetFrameStats(); + ResetFrameStats(); return true; } if (strCommand.compare(L"$vsync off") == 0) { DisableVSync(); + extern void ResetFrameStats(); + ResetFrameStats(); return true; } From 3a9c815d931a30e464388b853f25ec50d5b2f78a Mon Sep 17 00:00:00 2001 From: Mosch0512 Date: Sat, 7 Feb 2026 18:02:23 +0100 Subject: [PATCH 4/7] Split $fpscounter into simple FPS display and $details for full debug overlay Address PR review feedback: replace extern declarations with header include, extract magic numbers to named constants, use std::accumulate, fix highest FPS to track instantaneous values, rename misleading 0.1% low to slowest frame, fix frame time consistency. --- README.md | 2 + src/source/Scenes/SceneManager.cpp | 89 +++++++++++++++------ src/source/Scenes/SceneManager.h | 5 ++ src/source/Utilities/Log/muConsoleDebug.cpp | 19 +++-- 4 files changed, 86 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index b4ad985e3..ef4d479c5 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@ What I have done so far: * Change FPS-Limit: `$fps ` * Enable V-Sync: `$vsync on` * Disable V-Sync: `$vsync off` + * Show simple FPS counter: `$fpscounter on` / `$fpscounter off` + * Show detailed performance overlay (FPS stats, percentiles, frame graph): `$details on` / `$details off` * 🔥 Optimized some OpenGL calls by using vertex arrays. This should result in a better frame rate when many players and objects are visible. * 🔥 Added inventory and vault extensions. diff --git a/src/source/Scenes/SceneManager.cpp b/src/source/Scenes/SceneManager.cpp index 0c563f342..861b63679 100644 --- a/src/source/Scenes/SceneManager.cpp +++ b/src/source/Scenes/SceneManager.cpp @@ -5,6 +5,7 @@ #include "stdafx.h" #include #include +#include #include "SceneManager.h" //============================================================================= @@ -66,13 +67,32 @@ static bool g_bShowDebugInfo = false; #endif -void SetShowDebugInfo(bool enabled) { g_bShowDebugInfo = enabled; } +static bool g_bShowFpsCounter = false; + +void SetShowDebugInfo(bool enabled) +{ + g_bShowDebugInfo = enabled; + if (enabled) g_bShowFpsCounter = false; +} + +void SetShowFpsCounter(bool enabled) +{ + g_bShowFpsCounter = enabled; + if (enabled) g_bShowDebugInfo = false; +} //============================================================================= // Frame Statistics Tracker //============================================================================= -static constexpr int FRAME_HISTORY_SIZE = 300; // ~5 seconds at 60fps +static constexpr int FRAME_HISTORY_SIZE = 300; // ~5 seconds at 60fps +static constexpr float MIN_FRAME_TIME_MS = 0.5f; // clamp to 2000fps max +static constexpr double STATS_UPDATE_INTERVAL = 500.0; // ms between percentile recalculations +static constexpr int MIN_FRAMES_FOR_STATS = 10; +static constexpr float GRAPH_MAX_MS = 33.3f; // graph Y-axis scale (30fps) +static constexpr float THRESHOLD_60FPS_MS = 16.67f; // 60 FPS threshold +static constexpr float THRESHOLD_40FPS_MS = 25.0f; // 40 FPS threshold + static float s_frameTimesMs[FRAME_HISTORY_SIZE] = {}; static int s_frameIndex = 0; static int s_frameCount = 0; @@ -82,7 +102,7 @@ static double s_highestFps = 0.0; // Percentile stats (updated periodically) static float s_avgFps = 0.0f; static float s_onePercentLow = 0.0f; -static float s_pointOnePercentLow = 0.0f; +static float s_slowestFrameFps = 0.0f; static double s_lastStatsUpdate = 0.0; void ResetFrameStats() @@ -94,7 +114,7 @@ void ResetFrameStats() s_highestFps = 0.0; s_avgFps = 0.0f; s_onePercentLow = 0.0f; - s_pointOnePercentLow = 0.0f; + s_slowestFrameFps = 0.0f; s_lastStatsUpdate = 0.0; } @@ -104,17 +124,18 @@ static void UpdateFrameStats() if (s_lastFrameTime > 0.0) { double dt = now - s_lastFrameTime; - if (dt < 0.5) dt = 0.5; // clamp to 2000fps max + if (dt < MIN_FRAME_TIME_MS) dt = MIN_FRAME_TIME_MS; s_frameTimesMs[s_frameIndex] = static_cast(dt); s_frameIndex = (s_frameIndex + 1) % FRAME_HISTORY_SIZE; if (s_frameCount < FRAME_HISTORY_SIZE) s_frameCount++; + + double instantaneousFps = 1000.0 / dt; + if (instantaneousFps > s_highestFps) s_highestFps = instantaneousFps; } s_lastFrameTime = now; - if (FPS_AVG > s_highestFps) s_highestFps = FPS_AVG; - - // Update percentile stats every 500ms - if (now - s_lastStatsUpdate > 500.0 && s_frameCount > 10) + // Update percentile stats periodically + if (now - s_lastStatsUpdate > STATS_UPDATE_INTERVAL && s_frameCount > MIN_FRAMES_FOR_STATS) { s_lastStatsUpdate = now; @@ -124,20 +145,18 @@ static void UpdateFrameStats() std::sort(sorted, sorted + s_frameCount, std::greater()); // Average - float sum = 0.0f; - for (int i = 0; i < s_frameCount; i++) sum += sorted[i]; + float sum = std::accumulate(sorted, sorted + s_frameCount, 0.0f); float avgMs = sum / s_frameCount; s_avgFps = (avgMs > 0.0f) ? 1000.0f / avgMs : 0.0f; // 1% low: average of the slowest 1% of frames int onePercCount = std::max(1, s_frameCount / 100); - float onePercSum = 0.0f; - for (int i = 0; i < onePercCount; i++) onePercSum += sorted[i]; + float onePercSum = std::accumulate(sorted, sorted + onePercCount, 0.0f); float onePercAvgMs = onePercSum / onePercCount; s_onePercentLow = (onePercAvgMs > 0.0f) ? 1000.0f / onePercAvgMs : 0.0f; - // 0.1% low: the single slowest frame in the window - s_pointOnePercentLow = (sorted[0] > 0.0f) ? 1000.0f / sorted[0] : 0.0f; + // Slowest frame: the single slowest frame in the window + s_slowestFrameFps = (sorted[0] > 0.0f) ? 1000.0f / sorted[0] : 0.0f; } } @@ -409,8 +428,7 @@ static void RenderFrameGraph(float graphX, float graphY, float graphW, float gra glEnd(); // Target line at 16.67ms (60fps) - float maxMs = 33.3f; // graph scales to 33.3ms (30fps) max - float target60 = 16.67f / maxMs; + float target60 = THRESHOLD_60FPS_MS / GRAPH_MAX_MS; float lineY = glBottom + target60 * gh; glColor4f(0.3f, 0.8f, 0.3f, 0.5f); glBegin(GL_LINES); @@ -426,13 +444,13 @@ static void RenderFrameGraph(float graphX, float graphY, float graphW, float gra { int idx = (oldest + i) % FRAME_HISTORY_SIZE; float ms = s_frameTimesMs[idx]; - float norm = std::min(ms / maxMs, 1.0f); + float norm = std::min(ms / GRAPH_MAX_MS, 1.0f); float barH = norm * gh; - // Color: green < 16ms, yellow < 25ms, red >= 25ms - if (ms < 16.67f) + // Color: green < 16.67ms, yellow < 25ms, red >= 25ms + if (ms < THRESHOLD_60FPS_MS) glColor4f(0.2f, 0.9f, 0.2f, 0.8f); - else if (ms < 25.0f) + else if (ms < THRESHOLD_40FPS_MS) glColor4f(0.9f, 0.9f, 0.2f, 0.8f); else glColor4f(0.9f, 0.2f, 0.2f, 0.8f); @@ -473,9 +491,9 @@ static void RenderDebugInfo() FPS_AVG, s_avgFps, s_highestFps, IsVSyncEnabled(), CPU_AVG); g_pRenderText->RenderText(10, y, szLine); y += 10; - swprintf(szLine, L"1%% Low: %.1f 0.1%% Low: %.1f Frame: %.2fms", - s_onePercentLow, s_pointOnePercentLow, - (FPS_AVG > 0.0) ? 1000.0 / FPS_AVG : 0.0); + swprintf(szLine, L"1%% Low: %.1f Slowest: %.1f Frame: %.2fms", + s_onePercentLow, s_slowestFrameFps, + (s_avgFps > 0.0f) ? 1000.0f / s_avgFps : 0.0f); g_pRenderText->RenderText(10, y, szLine); y += 10; swprintf(szLine, L"MousePos: %d %d %d", MouseX, MouseY, MouseLButtonPush); @@ -491,6 +509,28 @@ static void RenderDebugInfo() EndBitmap(); } +/** + * @brief Renders a simple FPS counter overlay showing only current FPS. + */ +static void RenderFpsCounter() +{ + if (!g_bShowFpsCounter) + return; + + BeginBitmap(); + + wchar_t szLine[64]; + g_pRenderText->SetFont(g_hFontBold); + g_pRenderText->SetBgColor(0, 0, 0, 100); + g_pRenderText->SetTextColor(255, 255, 255, 200); + + swprintf(szLine, L"FPS: %.1f", FPS_AVG); + g_pRenderText->RenderText(10, 26, szLine); + + g_pRenderText->SetFont(g_hFont); + EndBitmap(); +} + /** * @brief Checks and handles server connection loss. */ @@ -871,6 +911,7 @@ void MainScene(HDC hDC) { Success = RenderCurrentScene(hDC); RenderDebugInfo(); + RenderFpsCounter(); if (Success) { diff --git a/src/source/Scenes/SceneManager.h b/src/source/Scenes/SceneManager.h index 1f9cc3199..742a6b351 100644 --- a/src/source/Scenes/SceneManager.h +++ b/src/source/Scenes/SceneManager.h @@ -113,3 +113,8 @@ void MainScene(HDC hDC); // FPS management (legacy - use g_frameTiming instead) void SetTargetFps(double targetFps); double GetTargetFps(); + +// Debug overlay controls +void SetShowDebugInfo(bool enabled); +void SetShowFpsCounter(bool enabled); +void ResetFrameStats(); diff --git a/src/source/Utilities/Log/muConsoleDebug.cpp b/src/source/Utilities/Log/muConsoleDebug.cpp index 32c01ca7f..75a680c70 100644 --- a/src/source/Utilities/Log/muConsoleDebug.cpp +++ b/src/source/Utilities/Log/muConsoleDebug.cpp @@ -15,6 +15,7 @@ #include "GlobalBitmap.h" #include "ZzzTexture.h" #include "Scenes/SceneCore.h" +#include "Scenes/SceneManager.h" #ifdef _EDITOR #include "../MuEditor/UI/Console/MuEditorConsoleUI.h" @@ -81,14 +82,24 @@ bool CmuConsoleDebug::CheckCommand(const std::wstring& strCommand) { if (strCommand.compare(L"$fpscounter on") == 0) { - extern void SetShowDebugInfo(bool); - SetShowDebugInfo(true); + SetShowFpsCounter(true); return true; } if (strCommand.compare(L"$fpscounter off") == 0) { - extern void SetShowDebugInfo(bool); + SetShowFpsCounter(false); + return true; + } + + if (strCommand.compare(L"$details on") == 0) + { + SetShowDebugInfo(true); + return true; + } + + if (strCommand.compare(L"$details off") == 0) + { SetShowDebugInfo(false); return true; } @@ -105,7 +116,6 @@ bool CmuConsoleDebug::CheckCommand(const std::wstring& strCommand) { EnableVSync(); SetTargetFps(-1); // unlimited - extern void ResetFrameStats(); ResetFrameStats(); return true; } @@ -113,7 +123,6 @@ bool CmuConsoleDebug::CheckCommand(const std::wstring& strCommand) if (strCommand.compare(L"$vsync off") == 0) { DisableVSync(); - extern void ResetFrameStats(); ResetFrameStats(); return true; } From 6b4ada2d969c8c9ff594efc91e3b6dc166950de3 Mon Sep 17 00:00:00 2001 From: Mosch0512 Date: Sat, 7 Feb 2026 18:07:31 +0100 Subject: [PATCH 5/7] Simplify `$vsync` command documentation in README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index ef4d479c5..45145880b 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,7 @@ What I have done so far: * The options menu includes a checkbox to reduce effects to achieve higher frame rates. * Chat commands: * Change FPS-Limit: `$fps ` - * Enable V-Sync: `$vsync on` - * Disable V-Sync: `$vsync off` + * V-Sync: `$vsync on` / `$vsync off` * Show simple FPS counter: `$fpscounter on` / `$fpscounter off` * Show detailed performance overlay (FPS stats, percentiles, frame graph): `$details on` / `$details off` * 🔥 Optimized some OpenGL calls by using vertex arrays. This should result in From 03b5845877078720ef80569573ec9473d13240fc Mon Sep 17 00:00:00 2001 From: Mosch0512 Date: Sun, 8 Feb 2026 17:11:53 +0100 Subject: [PATCH 6/7] Batch frame graph draw calls and use else-if chain for command parsing Move glBegin/glEnd outside the frame bar loop to reduce draw calls. Use else-if chain in CheckCommand to skip unnecessary comparisons. --- src/source/Scenes/SceneManager.cpp | 4 ++-- src/source/Utilities/Log/muConsoleDebug.cpp | 21 +++++++-------------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/source/Scenes/SceneManager.cpp b/src/source/Scenes/SceneManager.cpp index 861b63679..7f35e1b92 100644 --- a/src/source/Scenes/SceneManager.cpp +++ b/src/source/Scenes/SceneManager.cpp @@ -440,6 +440,7 @@ static void RenderFrameGraph(float graphX, float graphY, float graphW, float gra float barW = gw / FRAME_HISTORY_SIZE; int oldest = (s_frameCount < FRAME_HISTORY_SIZE) ? 0 : s_frameIndex; + glBegin(GL_QUADS); for (int i = 0; i < s_frameCount; i++) { int idx = (oldest + i) % FRAME_HISTORY_SIZE; @@ -456,13 +457,12 @@ static void RenderFrameGraph(float graphX, float graphY, float graphW, float gra glColor4f(0.9f, 0.2f, 0.2f, 0.8f); float bx = gx + i * barW; - glBegin(GL_QUADS); glVertex2f(bx, glBottom); glVertex2f(bx + barW, glBottom); glVertex2f(bx + barW, glBottom + barH); glVertex2f(bx, glBottom + barH); - glEnd(); } + glEnd(); glEnable(GL_TEXTURE_2D); } diff --git a/src/source/Utilities/Log/muConsoleDebug.cpp b/src/source/Utilities/Log/muConsoleDebug.cpp index 75a680c70..13cb9a65b 100644 --- a/src/source/Utilities/Log/muConsoleDebug.cpp +++ b/src/source/Utilities/Log/muConsoleDebug.cpp @@ -85,49 +85,42 @@ bool CmuConsoleDebug::CheckCommand(const std::wstring& strCommand) SetShowFpsCounter(true); return true; } - - if (strCommand.compare(L"$fpscounter off") == 0) + else if (strCommand.compare(L"$fpscounter off") == 0) { SetShowFpsCounter(false); return true; } - - if (strCommand.compare(L"$details on") == 0) + else if (strCommand.compare(L"$details on") == 0) { SetShowDebugInfo(true); return true; } - - if (strCommand.compare(L"$details off") == 0) + else if (strCommand.compare(L"$details off") == 0) { SetShowDebugInfo(false); return true; } - - if (strCommand.compare(0, 4, L"$fps") == 0) + else if (strCommand.compare(0, 4, L"$fps") == 0) { auto fps_str = strCommand.substr(5); auto target_fps = std::stof(fps_str); SetTargetFps(target_fps); return true; } - - if (strCommand.compare(L"$vsync on") == 0) + else if (strCommand.compare(L"$vsync on") == 0) { EnableVSync(); SetTargetFps(-1); // unlimited ResetFrameStats(); return true; } - - if (strCommand.compare(L"$vsync off") == 0) + else if (strCommand.compare(L"$vsync off") == 0) { DisableVSync(); ResetFrameStats(); return true; } - - if (strCommand.compare(0, 7, L"$winmsg") == 0) + else if (strCommand.compare(0, 7, L"$winmsg") == 0) { auto str_limit = strCommand.substr(8); auto message_limit = std::stof(str_limit); From de4f052d6234c7b74e48037dfba22575fa2da6cf Mon Sep 17 00:00:00 2001 From: Mosch0512 Date: Sun, 8 Feb 2026 17:28:56 +0100 Subject: [PATCH 7/7] Extract debug overlay layout values into named constants --- src/source/Scenes/SceneManager.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/source/Scenes/SceneManager.cpp b/src/source/Scenes/SceneManager.cpp index 7f35e1b92..22d065b68 100644 --- a/src/source/Scenes/SceneManager.cpp +++ b/src/source/Scenes/SceneManager.cpp @@ -92,6 +92,12 @@ static constexpr int MIN_FRAMES_FOR_STATS = 10; static constexpr float GRAPH_MAX_MS = 33.3f; // graph Y-axis scale (30fps) static constexpr float THRESHOLD_60FPS_MS = 16.67f; // 60 FPS threshold static constexpr float THRESHOLD_40FPS_MS = 25.0f; // 40 FPS threshold +static constexpr float DEBUG_TEXT_X = 10.0f; // debug overlay X position +static constexpr int DEBUG_TEXT_Y_START = 26; // debug overlay Y start +static constexpr int DEBUG_TEXT_LINE_HEIGHT = 10; // line spacing +static constexpr float DEBUG_GRAPH_WIDTH = 200.0f; // frame graph width +static constexpr float DEBUG_GRAPH_HEIGHT = 40.0f; // frame graph height +static constexpr float DEBUG_GRAPH_Y_OFFSET = 2.0f; // gap between text and graph static float s_frameTimesMs[FRAME_HISTORY_SIZE] = {}; static int s_frameIndex = 0; @@ -486,24 +492,24 @@ static void RenderDebugInfo() g_pRenderText->SetBgColor(0, 0, 0, 100); g_pRenderText->SetTextColor(255, 255, 255, 200); - int y = 26; + int y = DEBUG_TEXT_Y_START; swprintf(szLine, L"FPS: %.1f Avg: %.1f Max: %.1f Vsync: %d CPU: %.1f%%", FPS_AVG, s_avgFps, s_highestFps, IsVSyncEnabled(), CPU_AVG); - g_pRenderText->RenderText(10, y, szLine); y += 10; + g_pRenderText->RenderText((int)DEBUG_TEXT_X, y, szLine); y += DEBUG_TEXT_LINE_HEIGHT; swprintf(szLine, L"1%% Low: %.1f Slowest: %.1f Frame: %.2fms", s_onePercentLow, s_slowestFrameFps, (s_avgFps > 0.0f) ? 1000.0f / s_avgFps : 0.0f); - g_pRenderText->RenderText(10, y, szLine); y += 10; + g_pRenderText->RenderText((int)DEBUG_TEXT_X, y, szLine); y += DEBUG_TEXT_LINE_HEIGHT; swprintf(szLine, L"MousePos: %d %d %d", MouseX, MouseY, MouseLButtonPush); - g_pRenderText->RenderText(10, y, szLine); y += 10; + g_pRenderText->RenderText((int)DEBUG_TEXT_X, y, szLine); y += DEBUG_TEXT_LINE_HEIGHT; swprintf(szLine, L"Camera3D: %.1f %.1f:%.1f:%.1f", CameraFOV, CameraAngle[0], CameraAngle[1], CameraAngle[2]); - g_pRenderText->RenderText(10, y, szLine); y += 10; + g_pRenderText->RenderText((int)DEBUG_TEXT_X, y, szLine); y += DEBUG_TEXT_LINE_HEIGHT; // Frame time graph below text - RenderFrameGraph(10.0f, (float)(y + 2), 200.0f, 40.0f); + RenderFrameGraph(DEBUG_TEXT_X, (float)y + DEBUG_GRAPH_Y_OFFSET, DEBUG_GRAPH_WIDTH, DEBUG_GRAPH_HEIGHT); g_pRenderText->SetFont(g_hFont); EndBitmap(); @@ -525,7 +531,7 @@ static void RenderFpsCounter() g_pRenderText->SetTextColor(255, 255, 255, 200); swprintf(szLine, L"FPS: %.1f", FPS_AVG); - g_pRenderText->RenderText(10, 26, szLine); + g_pRenderText->RenderText((int)DEBUG_TEXT_X, DEBUG_TEXT_Y_START, szLine); g_pRenderText->SetFont(g_hFont); EndBitmap();