feat: ImGui 调试面板分组整理
Scene/Rendering/Environment/GPU Timings/Frame 五个 CollapsingHeader; 功能开关用 checkbox 条件显隐联动参数(Bloom 勾选才出现 threshold/ strength),无参数开关横排平铺。
This commit is contained in:
+122
-108
@@ -162,130 +162,144 @@ namespace
|
|||||||
void OnRenderOverlay() override
|
void OnRenderOverlay() override
|
||||||
{
|
{
|
||||||
ImGui::Begin("Scene Debug");
|
ImGui::Begin("Scene Debug");
|
||||||
|
|
||||||
// 阴影光源方向:拖动滑条实时看影子变化
|
|
||||||
if (auto* light = m_KeyLight.TryGetComponent<LightComponent>())
|
|
||||||
{
|
|
||||||
ImGui::Text("Key Light (shadow caster)");
|
|
||||||
ImGui::SliderFloat3("direction",
|
|
||||||
&light->direction.x, -1.0f, 1.0f);
|
|
||||||
ImGui::SliderFloat("intensity", &light->color.a, 0.0f, 20.0f);
|
|
||||||
if (ImGui::Button("reset"))
|
|
||||||
{
|
|
||||||
light->direction = glm::vec3(-0.5f, -0.6f, -0.35f);
|
|
||||||
light->color.a = 2.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tonemap + Bloom 参数(HDR 后处理输出端)
|
|
||||||
auto& renderer = GetRenderer();
|
auto& renderer = GetRenderer();
|
||||||
ImGui::Separator();
|
|
||||||
ImGui::Text("Tonemap");
|
|
||||||
f32 exposure = renderer.GetExposure();
|
|
||||||
if (ImGui::SliderFloat("exposure", &exposure, 0.1f, 4.0f))
|
|
||||||
{
|
|
||||||
renderer.SetExposure(exposure);
|
|
||||||
}
|
|
||||||
bool aces = renderer.GetUseACES();
|
|
||||||
if (ImGui::Checkbox("ACES", &aces))
|
|
||||||
{
|
|
||||||
renderer.SetUseACES(aces);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Text("Bloom");
|
// ---- Scene:场景内容(灯/动画) ----
|
||||||
f32 threshold = renderer.GetBloomThreshold();
|
if (ImGui::CollapsingHeader("Scene", ImGuiTreeNodeFlags_DefaultOpen))
|
||||||
if (ImGui::SliderFloat("threshold", &threshold, 0.0f, 2.0f))
|
|
||||||
{
|
{
|
||||||
renderer.SetBloomThreshold(threshold);
|
// 阴影光源(无开关,控件平铺聚拢)
|
||||||
}
|
if (auto* light = m_KeyLight.TryGetComponent<LightComponent>())
|
||||||
f32 strength = renderer.GetBloomStrength();
|
|
||||||
if (ImGui::SliderFloat("strength", &strength, 0.0f, 2.0f))
|
|
||||||
{
|
|
||||||
renderer.SetBloomStrength(strength);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Text("Features");
|
|
||||||
bool shadows = renderer.GetShadowsEnabled();
|
|
||||||
if (ImGui::Checkbox("Shadows", &shadows))
|
|
||||||
{
|
|
||||||
renderer.SetShadowsEnabled(shadows);
|
|
||||||
}
|
|
||||||
bool taa = renderer.GetTAAEnabled();
|
|
||||||
if (ImGui::Checkbox("TAA", &taa))
|
|
||||||
{
|
|
||||||
renderer.SetTAAEnabled(taa);
|
|
||||||
}
|
|
||||||
bool bloom = renderer.GetBloomEnabled();
|
|
||||||
if (ImGui::Checkbox("Bloom", &bloom))
|
|
||||||
{
|
|
||||||
renderer.SetBloomEnabled(bloom);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 动态环境切换(Assets 层加载 → Renderer 换绑;缓存去重)
|
|
||||||
ImGui::Separator();
|
|
||||||
ImGui::Text("Environment (IBL)");
|
|
||||||
int envIdx = m_EnvIndex;
|
|
||||||
if (ImGui::Combo("env", &envIdx, kEnvNames, kEnvCount))
|
|
||||||
{
|
|
||||||
const auto ref = GetAssets().LoadEnvironment(kEnvPaths[envIdx]);
|
|
||||||
if (ref.Valid())
|
|
||||||
{
|
{
|
||||||
renderer.SetEnvironment(GetAssets().GetEnvironment(ref));
|
ImGui::Text("Key Light (shadow caster)");
|
||||||
m_EnvIndex = envIdx;
|
ImGui::SliderFloat3("direction",
|
||||||
|
&light->direction.x, -1.0f, 1.0f);
|
||||||
|
ImGui::SliderFloat("intensity", &light->color.a, 0.0f, 20.0f);
|
||||||
|
if (ImGui::Button("reset"))
|
||||||
|
{
|
||||||
|
light->direction = glm::vec3(-0.5f, -0.6f, -0.35f);
|
||||||
|
light->color.a = 2.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::Checkbox("Pause Animation", &m_PauseAnim);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Rendering:渲染管线参数与开关 ----
|
||||||
|
if (ImGui::CollapsingHeader("Rendering", ImGuiTreeNodeFlags_DefaultOpen))
|
||||||
|
{
|
||||||
|
// Tonemap(无开关,平铺)
|
||||||
|
f32 exposure = renderer.GetExposure();
|
||||||
|
if (ImGui::SliderFloat("exposure", &exposure, 0.1f, 4.0f))
|
||||||
|
{
|
||||||
|
renderer.SetExposure(exposure);
|
||||||
|
}
|
||||||
|
bool aces = renderer.GetUseACES();
|
||||||
|
if (ImGui::Checkbox("ACES", &aces))
|
||||||
|
{
|
||||||
|
renderer.SetUseACES(aces);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bloom:开关即显隐——勾上才显示参数
|
||||||
|
bool bloom = renderer.GetBloomEnabled();
|
||||||
|
if (ImGui::Checkbox("Bloom", &bloom))
|
||||||
|
{
|
||||||
|
renderer.SetBloomEnabled(bloom);
|
||||||
|
}
|
||||||
|
if (bloom)
|
||||||
|
{
|
||||||
|
f32 threshold = renderer.GetBloomThreshold();
|
||||||
|
if (ImGui::SliderFloat("threshold", &threshold, 0.0f, 2.0f))
|
||||||
|
{
|
||||||
|
renderer.SetBloomThreshold(threshold);
|
||||||
|
}
|
||||||
|
f32 strength = renderer.GetBloomStrength();
|
||||||
|
if (ImGui::SliderFloat("strength", &strength, 0.0f, 2.0f))
|
||||||
|
{
|
||||||
|
renderer.SetBloomStrength(strength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 无参数的纯开关:横排平铺
|
||||||
|
bool shadows = renderer.GetShadowsEnabled();
|
||||||
|
if (ImGui::Checkbox("Shadows", &shadows))
|
||||||
|
{
|
||||||
|
renderer.SetShadowsEnabled(shadows);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
bool taa = renderer.GetTAAEnabled();
|
||||||
|
if (ImGui::Checkbox("TAA", &taa))
|
||||||
|
{
|
||||||
|
renderer.SetTAAEnabled(taa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::Text("(switch = compute pre-integrate, ms-level)");
|
|
||||||
|
|
||||||
// 调试视图:单看某个 pass 的中间输出(类 UE pass debug)
|
// ---- Environment:IBL 环境 + 调试视图(决定"看什么") ----
|
||||||
const auto& viewNames = renderer.GetDebugViewNames();
|
if (ImGui::CollapsingHeader("Environment", ImGuiTreeNodeFlags_DefaultOpen))
|
||||||
int view = renderer.GetDebugView();
|
|
||||||
if (ImGui::Combo("Debug View", &view, viewNames.data(),
|
|
||||||
static_cast<int>(viewNames.size())))
|
|
||||||
{
|
{
|
||||||
renderer.SetDebugView(view);
|
// 动态环境切换(Assets 层加载 → Renderer 换绑;缓存去重)
|
||||||
}
|
ImGui::Text("Environment (IBL)");
|
||||||
ImGui::Checkbox("Pause Animation", &m_PauseAnim);
|
int envIdx = m_EnvIndex;
|
||||||
|
if (ImGui::Combo("env", &envIdx, kEnvNames, kEnvCount))
|
||||||
|
{
|
||||||
|
const auto ref = GetAssets().LoadEnvironment(kEnvPaths[envIdx]);
|
||||||
|
if (ref.Valid())
|
||||||
|
{
|
||||||
|
renderer.SetEnvironment(GetAssets().GetEnvironment(ref));
|
||||||
|
m_EnvIndex = envIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::Text("(switch = compute pre-integrate, ms-level)");
|
||||||
|
|
||||||
// Pass 级 GPU 耗时(RG timestamp)
|
// 调试视图:单看某个 pass 的中间输出(类 UE pass debug)
|
||||||
ImGui::Separator();
|
const auto& viewNames = renderer.GetDebugViewNames();
|
||||||
ImGui::Text("GPU Timings");
|
int view = renderer.GetDebugView();
|
||||||
ImGui::Text("instances: %u main / %u shadow",
|
if (ImGui::Combo("Debug View", &view, viewNames.data(),
|
||||||
renderer.GetMainInstanceCount(),
|
static_cast<int>(viewNames.size())))
|
||||||
renderer.GetShadowInstanceCount());
|
{
|
||||||
const auto& names = renderer.GetPassNames();
|
renderer.SetDebugView(view);
|
||||||
const auto& times = renderer.GetPassGpuMs();
|
}
|
||||||
for (size_t i = 0; i < names.size() && i < times.size(); ++i)
|
|
||||||
{
|
|
||||||
ImGui::Text(" %-12s %.3f ms", names[i].c_str(), times[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 帧率控制
|
// ---- GPU Timings:只读遥测(默认折叠,不占面板高度) ----
|
||||||
auto& app = *this;
|
if (ImGui::CollapsingHeader("GPU Timings"))
|
||||||
ImGui::Separator();
|
|
||||||
ImGui::Text("Frame");
|
|
||||||
bool vsync = app.GetVSync();
|
|
||||||
if (ImGui::Checkbox("VSync", &vsync))
|
|
||||||
{
|
{
|
||||||
app.SetVSync(vsync);
|
// Pass 级 GPU 耗时(RG timestamp)
|
||||||
|
ImGui::Text("instances: %u main / %u shadow",
|
||||||
|
renderer.GetMainInstanceCount(),
|
||||||
|
renderer.GetShadowInstanceCount());
|
||||||
|
const auto& names = renderer.GetPassNames();
|
||||||
|
const auto& times = renderer.GetPassGpuMs();
|
||||||
|
for (size_t i = 0; i < names.size() && i < times.size(); ++i)
|
||||||
|
{
|
||||||
|
ImGui::Text(" %-12s %.3f ms", names[i].c_str(), times[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Frame:帧率控制与显示 ----
|
||||||
|
if (ImGui::CollapsingHeader("Frame", ImGuiTreeNodeFlags_DefaultOpen))
|
||||||
|
{
|
||||||
|
auto& app = *this;
|
||||||
|
bool vsync = app.GetVSync();
|
||||||
|
if (ImGui::Checkbox("VSync", &vsync))
|
||||||
|
{
|
||||||
|
app.SetVSync(vsync);
|
||||||
|
if (!vsync)
|
||||||
|
{
|
||||||
|
const f32 target = app.GetTargetFps();
|
||||||
|
app.SetTargetFps(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!vsync)
|
if (!vsync)
|
||||||
{
|
{
|
||||||
const f32 target = app.GetTargetFps();
|
f32 target = app.GetTargetFps();
|
||||||
app.SetTargetFps(target);
|
if (ImGui::SliderFloat("target fps", &target, 24.0f, 360.0f, "%.0f"))
|
||||||
|
{
|
||||||
|
app.SetTargetFps(target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
ImGui::Text("fps: %.1f frame: %llu",
|
||||||
|
1.0f / GetDeltaTime(),
|
||||||
|
static_cast<unsigned long long>(GetFrameCount()));
|
||||||
}
|
}
|
||||||
if (!vsync)
|
|
||||||
{
|
|
||||||
f32 target = app.GetTargetFps();
|
|
||||||
if (ImGui::SliderFloat("target fps", &target, 24.0f, 360.0f, "%.0f"))
|
|
||||||
{
|
|
||||||
app.SetTargetFps(target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Separator();
|
|
||||||
ImGui::Text("fps: %.1f frame: %llu",
|
|
||||||
1.0f / GetDeltaTime(),
|
|
||||||
static_cast<unsigned long long>(GetFrameCount()));
|
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user