From f71276fec04c317d07bfe768ebfbe1b28ddd60e7 Mon Sep 17 00:00:00 2001 From: hachem Date: Mon, 24 Aug 2026 03:57:40 +0200 Subject: feat: work on render path exporting --- src/ui/ui_layer.cpp | 39 +++++++++++++++++++++++++++++++-------- src/ui/workspace.h | 2 ++ 2 files changed, 33 insertions(+), 8 deletions(-) (limited to 'src/ui') diff --git a/src/ui/ui_layer.cpp b/src/ui/ui_layer.cpp index 40c395d..f44223d 100644 --- a/src/ui/ui_layer.cpp +++ b/src/ui/ui_layer.cpp @@ -270,31 +270,54 @@ namespace Donut public: auto name() const -> const char* override { return "Export"; } auto view() const -> View override { return View::None; } - auto on_ui(const UIContext&) -> void override + auto on_ui(const UIContext& ctx) -> void override { - ImGui::TextDisabled("Render observables to disk for analysis."); + ImGui::TextDisabled("Render the black hole + observables to disk for analysis."); ImGui::Spacing(); if (ImGui::CollapsingHeader("Channels", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::Checkbox("Colour (tonemapped)", &m_color); + ImGui::Checkbox("Colour (tone-mapped)", &m_color); ImGui::Checkbox("Redshift (g)", &m_redshift); ImGui::Checkbox("Emission temperature", &m_temperature); ImGui::Checkbox("Impact parameter", &m_impact); + ImGui::TextDisabled("Redshift & temperature are disk-only; impact is whole-frame (false-colour)."); } if (ImGui::CollapsingHeader("Output", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::Combo("Resolution", &m_resolution, "960 x 540\0" "1920 x 1080\0" "3840 x 2160\0"); - ImGui::Combo("Format", &m_format, "PNG\0" "EXR (HDR)\0" "CSV (data)\0"); + ImGui::Combo("Resolution", &m_resolution, "1280 x 720\0" "1920 x 1080\0" "2560 x 1440\0" "3840 x 2160\0"); + ImGui::Combo("Format", &m_format, "Display image (PNG)\0" "Raw float image (PFM)\0" "Raw values (CSV)\0"); + if (m_format == 0) ImGui::TextDisabled("Tone-mapped colour / false-coloured observables."); + else ImGui::TextDisabled("Actual physical values: g, temperature (K), impact (r_s)."); } + ImGui::Spacing(); - ImGui::BeginDisabled(); - ImGui::Button("Export frame", ImVec2(-1.0f, 0.0f)); + const bool any = m_color || m_redshift || m_temperature || m_impact; + ImGui::BeginDisabled(!any); + if (ImGui::Button("Export frame", ImVec2(-1.0f, 0.0f))) + { + static const int dims[][2] = { {1280,720}, {1920,1080}, {2560,1440}, {3840,2160} }; + ExportConfig cfg; + cfg.color = m_color; cfg.redshift = m_redshift; + cfg.temperature = m_temperature; cfg.impact = m_impact; + cfg.width = dims[m_resolution][0]; cfg.height = dims[m_resolution][1]; + cfg.format = static_cast(m_format); + m_written = ctx.actions.export_frame(cfg); + m_reported = true; + } ImGui::EndDisabled(); - ImGui::TextDisabled("Not wired up yet: needs the RHI readback path + G-buffer shader outputs."); + + if (m_reported) + { + if (m_written > 0) + ImGui::TextColored(ImVec4(0.55f, 0.85f, 0.45f, 1.0f), "Wrote %d PNG(s) to exports/", m_written); + else + ImGui::TextColored(ImVec4(0.95f, 0.45f, 0.35f, 1.0f), "Export failed (see log)"); + } } private: bool m_color = true, m_redshift = false, m_temperature = false, m_impact = false; int m_resolution = 1, m_format = 0; + int m_written = 0; bool m_reported = false; }; } diff --git a/src/ui/workspace.h b/src/ui/workspace.h index 04cc5db..608c829 100644 --- a/src/ui/workspace.h +++ b/src/ui/workspace.h @@ -1,6 +1,7 @@ #pragma once #include "rendering/view.h" +#include "rendering/export_config.h" #include namespace Donut @@ -16,6 +17,7 @@ namespace Donut virtual auto set_ui_scale(float scale) -> void = 0; virtual auto get_window_size(int& w, int& h) const -> void = 0; virtual auto is_fullscreen() const -> bool = 0; + virtual auto export_frame(const ExportConfig& cfg) -> int = 0; }; struct UIContext -- cgit v1.3