2026-02-02 12:24:50 -08:00
|
|
|
#include "rendering/performance_hud.hpp"
|
|
|
|
|
#include "rendering/renderer.hpp"
|
2026-03-07 22:03:28 -08:00
|
|
|
#include "rendering/vk_context.hpp"
|
2026-02-02 12:24:50 -08:00
|
|
|
#include "rendering/terrain_renderer.hpp"
|
|
|
|
|
#include "rendering/terrain_manager.hpp"
|
|
|
|
|
#include "rendering/water_renderer.hpp"
|
|
|
|
|
#include "rendering/skybox.hpp"
|
|
|
|
|
#include "rendering/celestial.hpp"
|
|
|
|
|
#include "rendering/starfield.hpp"
|
|
|
|
|
#include "rendering/clouds.hpp"
|
|
|
|
|
#include "rendering/lens_flare.hpp"
|
|
|
|
|
#include "rendering/weather.hpp"
|
|
|
|
|
#include "rendering/character_renderer.hpp"
|
|
|
|
|
#include "rendering/wmo_renderer.hpp"
|
2026-02-03 16:21:48 -08:00
|
|
|
#include "rendering/m2_renderer.hpp"
|
2026-02-02 12:24:50 -08:00
|
|
|
#include "rendering/camera.hpp"
|
|
|
|
|
#include <imgui.h>
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
#include <sstream>
|
|
|
|
|
#include <iomanip>
|
|
|
|
|
|
|
|
|
|
namespace wowee {
|
|
|
|
|
namespace rendering {
|
|
|
|
|
|
|
|
|
|
PerformanceHUD::PerformanceHUD() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PerformanceHUD::~PerformanceHUD() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PerformanceHUD::update(float deltaTime) {
|
|
|
|
|
if (!enabled) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Store frame time
|
|
|
|
|
frameTime = deltaTime;
|
|
|
|
|
frameTimeHistory.push_back(deltaTime);
|
|
|
|
|
|
|
|
|
|
// Keep history size limited
|
|
|
|
|
while (frameTimeHistory.size() > MAX_FRAME_HISTORY) {
|
|
|
|
|
frameTimeHistory.pop_front();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update stats periodically
|
|
|
|
|
updateTimer += deltaTime;
|
|
|
|
|
if (updateTimer >= UPDATE_INTERVAL) {
|
|
|
|
|
updateTimer = 0.0f;
|
|
|
|
|
calculateFPS();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PerformanceHUD::calculateFPS() {
|
|
|
|
|
if (frameTimeHistory.empty()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Current FPS (from last frame time)
|
|
|
|
|
currentFPS = frameTime > 0.0001f ? 1.0f / frameTime : 0.0f;
|
|
|
|
|
|
|
|
|
|
// Average FPS
|
|
|
|
|
float sum = 0.0f;
|
|
|
|
|
for (float ft : frameTimeHistory) {
|
|
|
|
|
sum += ft;
|
|
|
|
|
}
|
|
|
|
|
float avgFrameTime = sum / frameTimeHistory.size();
|
|
|
|
|
averageFPS = avgFrameTime > 0.0001f ? 1.0f / avgFrameTime : 0.0f;
|
|
|
|
|
|
|
|
|
|
// Min/Max FPS (from last 2 seconds)
|
|
|
|
|
minFPS = 10000.0f;
|
|
|
|
|
maxFPS = 0.0f;
|
|
|
|
|
for (float ft : frameTimeHistory) {
|
|
|
|
|
if (ft > 0.0001f) {
|
|
|
|
|
float fps = 1.0f / ft;
|
|
|
|
|
minFPS = std::min(minFPS, fps);
|
|
|
|
|
maxFPS = std::max(maxFPS, fps);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PerformanceHUD::render(const Renderer* renderer, const Camera* camera) {
|
|
|
|
|
if (!enabled || !renderer) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set window position based on setting
|
|
|
|
|
ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration |
|
|
|
|
|
ImGuiWindowFlags_AlwaysAutoResize |
|
|
|
|
|
ImGuiWindowFlags_NoSavedSettings |
|
|
|
|
|
ImGuiWindowFlags_NoFocusOnAppearing |
|
|
|
|
|
ImGuiWindowFlags_NoNav;
|
|
|
|
|
|
|
|
|
|
const float PADDING = 10.0f;
|
|
|
|
|
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
|
|
|
|
ImVec2 work_pos = viewport->WorkPos;
|
|
|
|
|
ImVec2 work_size = viewport->WorkSize;
|
|
|
|
|
ImVec2 window_pos, window_pos_pivot;
|
|
|
|
|
|
|
|
|
|
switch (position) {
|
|
|
|
|
case Position::TOP_LEFT:
|
|
|
|
|
window_pos.x = work_pos.x + PADDING;
|
|
|
|
|
window_pos.y = work_pos.y + PADDING;
|
|
|
|
|
window_pos_pivot.x = 0.0f;
|
|
|
|
|
window_pos_pivot.y = 0.0f;
|
|
|
|
|
break;
|
|
|
|
|
case Position::TOP_RIGHT:
|
|
|
|
|
window_pos.x = work_pos.x + work_size.x - PADDING;
|
|
|
|
|
window_pos.y = work_pos.y + PADDING;
|
|
|
|
|
window_pos_pivot.x = 1.0f;
|
|
|
|
|
window_pos_pivot.y = 0.0f;
|
|
|
|
|
break;
|
|
|
|
|
case Position::BOTTOM_LEFT:
|
|
|
|
|
window_pos.x = work_pos.x + PADDING;
|
|
|
|
|
window_pos.y = work_pos.y + work_size.y - PADDING;
|
|
|
|
|
window_pos_pivot.x = 0.0f;
|
|
|
|
|
window_pos_pivot.y = 1.0f;
|
|
|
|
|
break;
|
|
|
|
|
case Position::BOTTOM_RIGHT:
|
|
|
|
|
window_pos.x = work_pos.x + work_size.x - PADDING;
|
|
|
|
|
window_pos.y = work_pos.y + work_size.y - PADDING;
|
|
|
|
|
window_pos_pivot.x = 1.0f;
|
|
|
|
|
window_pos_pivot.y = 1.0f;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
|
|
|
|
|
ImGui::SetNextWindowBgAlpha(0.7f); // Transparent background
|
|
|
|
|
|
|
|
|
|
if (!ImGui::Begin("Performance", nullptr, flags)) {
|
|
|
|
|
ImGui::End();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FPS section
|
|
|
|
|
if (showFPS) {
|
|
|
|
|
ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "PERFORMANCE");
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
|
|
// Color-code FPS
|
|
|
|
|
ImVec4 fpsColor;
|
|
|
|
|
if (currentFPS >= 60.0f) {
|
|
|
|
|
fpsColor = ImVec4(0.0f, 1.0f, 0.0f, 1.0f); // Green
|
|
|
|
|
} else if (currentFPS >= 30.0f) {
|
|
|
|
|
fpsColor = ImVec4(1.0f, 1.0f, 0.0f, 1.0f); // Yellow
|
|
|
|
|
} else {
|
|
|
|
|
fpsColor = ImVec4(1.0f, 0.0f, 0.0f, 1.0f); // Red
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::Text("FPS: ");
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
ImGui::TextColored(fpsColor, "%.1f", currentFPS);
|
|
|
|
|
|
|
|
|
|
ImGui::Text("Avg: %.1f", averageFPS);
|
|
|
|
|
ImGui::Text("Min: %.1f", minFPS);
|
|
|
|
|
ImGui::Text("Max: %.1f", maxFPS);
|
|
|
|
|
ImGui::Text("Frame: %.2f ms", frameTime * 1000.0f);
|
|
|
|
|
|
2026-02-03 16:21:48 -08:00
|
|
|
ImGui::Spacing();
|
|
|
|
|
ImGui::TextColored(ImVec4(0.9f, 0.8f, 0.6f, 1.0f), "CPU TIMINGS (ms)");
|
|
|
|
|
ImGui::Text("Update: %.2f (Camera: %.2f)", renderer->getLastUpdateMs(), renderer->getLastCameraUpdateMs());
|
|
|
|
|
ImGui::Text("Render: %.2f (Terrain: %.2f, WMO: %.2f, M2: %.2f)",
|
|
|
|
|
renderer->getLastRenderMs(),
|
|
|
|
|
renderer->getLastTerrainRenderMs(),
|
|
|
|
|
renderer->getLastWMORenderMs(),
|
|
|
|
|
renderer->getLastM2RenderMs());
|
|
|
|
|
auto* wmoRenderer = renderer->getWMORenderer();
|
|
|
|
|
auto* m2Renderer = renderer->getM2Renderer();
|
|
|
|
|
if (wmoRenderer || m2Renderer) {
|
|
|
|
|
ImGui::Text("Collision queries:");
|
|
|
|
|
if (wmoRenderer) {
|
|
|
|
|
ImGui::Text(" WMO: %.2f ms (%u calls)",
|
|
|
|
|
wmoRenderer->getQueryTimeMs(), wmoRenderer->getQueryCallCount());
|
|
|
|
|
}
|
|
|
|
|
if (m2Renderer) {
|
|
|
|
|
ImGui::Text(" M2: %.2f ms (%u calls)",
|
|
|
|
|
m2Renderer->getQueryTimeMs(), m2Renderer->getQueryCallCount());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-02 12:24:50 -08:00
|
|
|
// Frame time graph
|
|
|
|
|
if (!frameTimeHistory.empty()) {
|
|
|
|
|
std::vector<float> frameTimesMs;
|
|
|
|
|
frameTimesMs.reserve(frameTimeHistory.size());
|
|
|
|
|
for (float ft : frameTimeHistory) {
|
|
|
|
|
frameTimesMs.push_back(ft * 1000.0f); // Convert to ms
|
|
|
|
|
}
|
|
|
|
|
ImGui::PlotLines("##frametime", frameTimesMs.data(), static_cast<int>(frameTimesMs.size()),
|
|
|
|
|
0, nullptr, 0.0f, 33.33f, ImVec2(200, 40));
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-07 22:03:28 -08:00
|
|
|
// FSR info
|
|
|
|
|
if (renderer->isFSREnabled()) {
|
|
|
|
|
ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "FSR 1.0: ON");
|
|
|
|
|
auto* ctx = renderer->getVkContext();
|
|
|
|
|
if (ctx) {
|
|
|
|
|
auto ext = ctx->getSwapchainExtent();
|
|
|
|
|
float sf = renderer->getFSRScaleFactor();
|
|
|
|
|
uint32_t iw = static_cast<uint32_t>(ext.width * sf) & ~1u;
|
|
|
|
|
uint32_t ih = static_cast<uint32_t>(ext.height * sf) & ~1u;
|
|
|
|
|
ImGui::Text(" %ux%u -> %ux%u (%.0f%%)", iw, ih, ext.width, ext.height, sf * 100.0f);
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-03-08 20:56:22 -07:00
|
|
|
if (renderer->isFSR2Enabled()) {
|
Add FSR3 Generic API path and harden runtime diagnostics
- AmdFsr3Runtime now probes both the legacy ffxFsr3* API and the newer
generic ffxCreateContext/ffxDispatch API; selects whichever the loaded
runtime library exports (GenericApi takes priority fallback)
- Generic API path implements full upscale + frame-generation context
creation, configure, dispatch, and destroy lifecycle
- dlopen error captured and surfaced in lastError_ on Linux so runtime
initialization failures are actionable
- FSR3 runtime init failure log now includes path kind, error string,
and loaded library path for easier debugging
- tools/generate_ffx_sdk_vk_permutations.sh added: auto-bootstraps
missing VK permutation headers; DXC auto-downloaded on Linux/Windows
MSYS2; macOS reads from PATH (CI installs via brew dxc)
- CMakeLists: add upscalers/include to probe include dirs, invoke
permutation script before SDK build, scope FFX pragma/ODR warning
suppressions to affected TUs, add runtime-copy dependency on wowee
- UI labels updated from "FSR2" → "FSR3" in settings, tuning panel,
performance HUD, and combo boxes
- CI macOS job now installs dxc via Homebrew for permutation codegen
2026-03-09 12:51:59 -07:00
|
|
|
ImGui::TextColored(ImVec4(0.4f, 0.9f, 1.0f, 1.0f), "FSR 3 Upscale: ON");
|
2026-03-08 21:08:17 -07:00
|
|
|
ImGui::Text(" JitterSign=%.2f", renderer->getFSR2JitterSign());
|
2026-03-08 23:35:39 -07:00
|
|
|
const bool fgEnabled = renderer->isAmdFsr3FramegenEnabled();
|
|
|
|
|
const bool fgReady = renderer->isAmdFsr3FramegenRuntimeReady();
|
|
|
|
|
const bool fgActive = renderer->isAmdFsr3FramegenRuntimeActive();
|
|
|
|
|
const char* fgStatus = "Disabled";
|
|
|
|
|
if (fgEnabled) {
|
|
|
|
|
fgStatus = fgActive ? "Active" : (fgReady ? "Ready (waiting/fallback)" : "Unavailable");
|
|
|
|
|
}
|
2026-03-09 00:01:45 -07:00
|
|
|
ImGui::Text(" FSR3 FG: %s (%s)", fgStatus, renderer->getAmdFsr3FramegenRuntimePath());
|
2026-03-09 01:15:49 -07:00
|
|
|
const std::string& fgErr = renderer->getAmdFsr3FramegenRuntimeError();
|
|
|
|
|
if (!fgErr.empty()) {
|
|
|
|
|
ImGui::TextWrapped(" FG Last Error: %s", fgErr.c_str());
|
|
|
|
|
}
|
2026-03-08 23:35:39 -07:00
|
|
|
ImGui::Text(" FG Dispatches: %zu", renderer->getAmdFsr3FramegenDispatchCount());
|
|
|
|
|
ImGui::Text(" Upscale Dispatches: %zu", renderer->getAmdFsr3UpscaleDispatchCount());
|
|
|
|
|
ImGui::Text(" FG Fallbacks: %zu", renderer->getAmdFsr3FallbackCount());
|
2026-03-08 20:56:22 -07:00
|
|
|
}
|
2026-03-12 17:01:20 -07:00
|
|
|
if (renderer->isFXAAEnabled()) {
|
2026-03-12 19:27:00 -07:00
|
|
|
if (renderer->isFSR2Enabled()) {
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 1.0f, 0.8f, 1.0f), "FXAA: ON (FSR3+FXAA combined)");
|
|
|
|
|
} else {
|
|
|
|
|
ImGui::TextColored(ImVec4(0.8f, 1.0f, 0.6f, 1.0f), "FXAA: ON");
|
|
|
|
|
}
|
2026-03-12 17:01:20 -07:00
|
|
|
}
|
2026-03-07 22:03:28 -08:00
|
|
|
|
2026-02-02 12:24:50 -08:00
|
|
|
ImGui::Spacing();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Renderer stats
|
|
|
|
|
if (showRenderer) {
|
|
|
|
|
auto* terrainRenderer = renderer->getTerrainRenderer();
|
|
|
|
|
if (terrainRenderer) {
|
|
|
|
|
ImGui::TextColored(ImVec4(0.0f, 1.0f, 1.0f, 1.0f), "RENDERING");
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
|
|
int totalChunks = terrainRenderer->getChunkCount();
|
|
|
|
|
int rendered = terrainRenderer->getRenderedChunkCount();
|
|
|
|
|
int culled = terrainRenderer->getCulledChunkCount();
|
|
|
|
|
int triangles = terrainRenderer->getTriangleCount();
|
|
|
|
|
|
|
|
|
|
ImGui::Text("Chunks: %d", totalChunks);
|
|
|
|
|
ImGui::Text("Rendered: %d", rendered);
|
|
|
|
|
ImGui::Text("Culled: %d", culled);
|
|
|
|
|
|
|
|
|
|
if (totalChunks > 0) {
|
|
|
|
|
float visiblePercent = (rendered * 100.0f) / totalChunks;
|
|
|
|
|
ImGui::Text("Visible: %.1f%%", visiblePercent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::Text("Triangles: %s",
|
|
|
|
|
triangles >= 1000000 ?
|
|
|
|
|
(std::to_string(triangles / 1000) + "K").c_str() :
|
|
|
|
|
std::to_string(triangles).c_str());
|
|
|
|
|
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Terrain streaming info
|
|
|
|
|
if (showTerrain) {
|
|
|
|
|
auto* terrainManager = renderer->getTerrainManager();
|
|
|
|
|
if (terrainManager) {
|
|
|
|
|
ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "TERRAIN");
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
|
|
ImGui::Text("Loaded tiles: %d", terrainManager->getLoadedTileCount());
|
|
|
|
|
|
|
|
|
|
auto currentTile = terrainManager->getCurrentTile();
|
|
|
|
|
ImGui::Text("Current tile: [%d,%d]", currentTile.x, currentTile.y);
|
|
|
|
|
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Water info
|
|
|
|
|
auto* waterRenderer = renderer->getWaterRenderer();
|
|
|
|
|
if (waterRenderer) {
|
|
|
|
|
ImGui::TextColored(ImVec4(0.2f, 0.5f, 1.0f, 1.0f), "WATER");
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
|
|
ImGui::Text("Surfaces: %d", waterRenderer->getSurfaceCount());
|
|
|
|
|
ImGui::Text("Enabled: %s", waterRenderer->isEnabled() ? "YES" : "NO");
|
|
|
|
|
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Skybox info
|
|
|
|
|
if (showTerrain) {
|
|
|
|
|
auto* skybox = renderer->getSkybox();
|
|
|
|
|
if (skybox) {
|
|
|
|
|
ImGui::TextColored(ImVec4(0.5f, 0.8f, 1.0f, 1.0f), "SKY");
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
|
|
float time = skybox->getTimeOfDay();
|
|
|
|
|
int hours = static_cast<int>(time);
|
|
|
|
|
int minutes = static_cast<int>((time - hours) * 60);
|
|
|
|
|
|
|
|
|
|
ImGui::Text("Time: %02d:%02d", hours, minutes);
|
|
|
|
|
ImGui::Text("Auto: %s", skybox->isTimeProgressionEnabled() ? "YES" : "NO");
|
|
|
|
|
|
|
|
|
|
// Celestial info
|
|
|
|
|
auto* celestial = renderer->getCelestial();
|
|
|
|
|
if (celestial) {
|
|
|
|
|
ImGui::Text("Sun/Moon: %s", celestial->isEnabled() ? "YES" : "NO");
|
|
|
|
|
|
|
|
|
|
// Moon phase info
|
|
|
|
|
float phase = celestial->getMoonPhase();
|
|
|
|
|
const char* phaseName = "Unknown";
|
|
|
|
|
if (phase < 0.0625f || phase >= 0.9375f) phaseName = "New";
|
|
|
|
|
else if (phase < 0.1875f) phaseName = "Wax Cresc";
|
|
|
|
|
else if (phase < 0.3125f) phaseName = "1st Qtr";
|
|
|
|
|
else if (phase < 0.4375f) phaseName = "Wax Gibb";
|
|
|
|
|
else if (phase < 0.5625f) phaseName = "Full";
|
|
|
|
|
else if (phase < 0.6875f) phaseName = "Wan Gibb";
|
|
|
|
|
else if (phase < 0.8125f) phaseName = "Last Qtr";
|
|
|
|
|
else phaseName = "Wan Cresc";
|
|
|
|
|
|
|
|
|
|
ImGui::Text("Moon: %s (%.0f%%)", phaseName, phase * 100.0f);
|
|
|
|
|
ImGui::Text("Cycling: %s", celestial->isMoonPhaseCycling() ? "YES" : "NO");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Star field info
|
|
|
|
|
auto* starField = renderer->getStarField();
|
|
|
|
|
if (starField) {
|
|
|
|
|
ImGui::Text("Stars: %d (%s)", starField->getStarCount(),
|
|
|
|
|
starField->isEnabled() ? "ON" : "OFF");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Cloud info
|
|
|
|
|
auto* clouds = renderer->getClouds();
|
|
|
|
|
if (clouds) {
|
|
|
|
|
ImGui::Text("Clouds: %s (%.0f%%)",
|
|
|
|
|
clouds->isEnabled() ? "ON" : "OFF",
|
|
|
|
|
clouds->getDensity() * 100.0f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Lens flare info
|
|
|
|
|
auto* lensFlare = renderer->getLensFlare();
|
|
|
|
|
if (lensFlare) {
|
|
|
|
|
ImGui::Text("Lens Flare: %s (%.0f%%)",
|
|
|
|
|
lensFlare->isEnabled() ? "ON" : "OFF",
|
|
|
|
|
lensFlare->getIntensity() * 100.0f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Weather info
|
|
|
|
|
if (showRenderer) {
|
|
|
|
|
auto* weather = renderer->getWeather();
|
|
|
|
|
if (weather) {
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.8f, 1.0f, 1.0f), "WEATHER");
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
|
|
const char* typeName = "None";
|
|
|
|
|
using WeatherType = rendering::Weather::Type;
|
|
|
|
|
auto type = weather->getWeatherType();
|
|
|
|
|
if (type == WeatherType::RAIN) typeName = "Rain";
|
|
|
|
|
else if (type == WeatherType::SNOW) typeName = "Snow";
|
|
|
|
|
|
|
|
|
|
ImGui::Text("Type: %s", typeName);
|
|
|
|
|
if (weather->isEnabled()) {
|
|
|
|
|
ImGui::Text("Particles: %d", weather->getParticleCount());
|
|
|
|
|
ImGui::Text("Intensity: %.0f%%", weather->getIntensity() * 100.0f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fog info
|
|
|
|
|
if (showRenderer) {
|
|
|
|
|
auto* terrainRenderer = renderer->getTerrainRenderer();
|
|
|
|
|
if (terrainRenderer) {
|
|
|
|
|
ImGui::TextColored(ImVec4(0.7f, 0.8f, 0.9f, 1.0f), "FOG");
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
|
|
ImGui::Text("Distance fog: %s", terrainRenderer->isFogEnabled() ? "ON" : "OFF");
|
|
|
|
|
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Character info
|
|
|
|
|
if (showRenderer) {
|
|
|
|
|
auto* charRenderer = renderer->getCharacterRenderer();
|
|
|
|
|
if (charRenderer) {
|
|
|
|
|
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.4f, 1.0f), "CHARACTERS");
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
|
|
ImGui::Text("Instances: %zu", charRenderer->getInstanceCount());
|
|
|
|
|
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WMO building info
|
|
|
|
|
if (showRenderer) {
|
|
|
|
|
auto* wmoRenderer = renderer->getWMORenderer();
|
|
|
|
|
if (wmoRenderer) {
|
|
|
|
|
ImGui::TextColored(ImVec4(0.8f, 0.7f, 0.6f, 1.0f), "WMO BUILDINGS");
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
|
|
ImGui::Text("Models: %u", wmoRenderer->getModelCount());
|
|
|
|
|
ImGui::Text("Instances: %u", wmoRenderer->getInstanceCount());
|
|
|
|
|
ImGui::Text("Triangles: %u", wmoRenderer->getTotalTriangleCount());
|
|
|
|
|
ImGui::Text("Draw Calls: %u", wmoRenderer->getDrawCallCount());
|
2026-02-05 17:20:30 -08:00
|
|
|
ImGui::Text("Floor Cache: %zu", wmoRenderer->getFloorCacheSize());
|
|
|
|
|
ImGui::Text("Dist Culled: %u groups", wmoRenderer->getDistanceCulledGroups());
|
2026-02-05 15:51:08 -08:00
|
|
|
if (wmoRenderer->isOcclusionCullingEnabled()) {
|
2026-02-05 17:20:30 -08:00
|
|
|
ImGui::Text("Occl Culled: %u groups", wmoRenderer->getOcclusionCulledGroups());
|
2026-02-05 15:51:08 -08:00
|
|
|
}
|
2026-02-05 15:31:00 -08:00
|
|
|
if (wmoRenderer->isPortalCullingEnabled()) {
|
|
|
|
|
ImGui::Text("Portal Culled: %u groups", wmoRenderer->getPortalCulledGroups());
|
|
|
|
|
}
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Zone info
|
|
|
|
|
{
|
|
|
|
|
const std::string& zoneName = renderer->getCurrentZoneName();
|
|
|
|
|
if (!zoneName.empty()) {
|
|
|
|
|
ImGui::TextColored(ImVec4(1.0f, 0.9f, 0.3f, 1.0f), "ZONE");
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
ImGui::Text("%s", zoneName.c_str());
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Camera info
|
|
|
|
|
if (showCamera && camera) {
|
|
|
|
|
ImGui::TextColored(ImVec4(1.0f, 0.5f, 0.0f, 1.0f), "CAMERA");
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
|
|
glm::vec3 pos = camera->getPosition();
|
|
|
|
|
ImGui::Text("Pos: %.1f, %.1f, %.1f", pos.x, pos.y, pos.z);
|
|
|
|
|
|
|
|
|
|
glm::vec3 forward = camera->getForward();
|
|
|
|
|
ImGui::Text("Dir: %.2f, %.2f, %.2f", forward.x, forward.y, forward.z);
|
|
|
|
|
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Controls help
|
|
|
|
|
if (showControls) {
|
|
|
|
|
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "CONTROLS");
|
|
|
|
|
ImGui::Separator();
|
2026-02-22 05:58:45 -08:00
|
|
|
|
|
|
|
|
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.5f, 1.0f), "Movement");
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "WASD: Move/Strafe");
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "Q/E: Turn left/right");
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "Space: Jump");
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "X: Sit/Stand");
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "~: Auto-run");
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "Z: Sheathe weapons");
|
|
|
|
|
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.5f, 1.0f), "UI Panels");
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "B: Bags/Inventory");
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "C: Character sheet");
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "L: Quest log");
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "N: Talents");
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "P: Spellbook");
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "M: World map");
|
|
|
|
|
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.5f, 1.0f), "Combat & Chat");
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "1-0,-,=: Action bar");
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "Tab: Target cycle");
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "Enter: Chat");
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "/: Chat command");
|
|
|
|
|
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.5f, 1.0f), "Debug");
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "F1: Toggle this HUD");
|
|
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "F4: Toggle shadows");
|
2026-02-19 20:36:25 -08:00
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "F7: Level-up FX");
|
2026-02-22 05:58:45 -08:00
|
|
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "Esc: Settings/Close");
|
2026-02-02 12:24:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::End();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace rendering
|
|
|
|
|
} // namespace wowee
|