Improve filament gui
* Added color to widgets which have changed from their initial values and the ability to revert to their initial values by clicking with the right mouse button * Added some reasonable range limits, which are especially useful for drag widgets PiperOrigin-RevId: 862220411 Change-Id: I1d2c61d8889d5ec29890d81b5f97af576cb5c611
This commit is contained in:
committed by
Copybara-Service
parent
40f2fe0977
commit
0eff7acf80
@@ -15,12 +15,15 @@
|
||||
#include "experimental/filament/filament/imgui_editor.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <any>
|
||||
#include <cstdint>
|
||||
#include <numbers>
|
||||
#include <optional>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <filament/ColorGrading.h>
|
||||
@@ -42,6 +45,35 @@ using filament::math::mat4;
|
||||
|
||||
using NameList = std::span<const char*>;
|
||||
|
||||
namespace {
|
||||
|
||||
using InitValues = std::unordered_map<ImGuiID, std::any>;
|
||||
|
||||
// Uses static storage (not heap) for a map that is never destroyed, avoiding
|
||||
// static destruction order issues. Note this is not causing a problem now but
|
||||
// may do so in the future.
|
||||
InitValues& GetInitValues() {
|
||||
alignas(InitValues) static char buf[sizeof(InitValues)];
|
||||
static InitValues* map = new (buf) InitValues();
|
||||
return *map;
|
||||
}
|
||||
|
||||
constexpr ImVec4 kModifiedColor = ImVec4(1.0f, 0.6f, 0.2f, 1.0f);
|
||||
|
||||
template <typename T>
|
||||
bool IsModified(ImGuiID id, const T& current_value) {
|
||||
auto it = GetInitValues().find(id);
|
||||
if (it == GetInitValues().end()) {
|
||||
GetInitValues()[id] = current_value;
|
||||
return false;
|
||||
}
|
||||
const T& a = current_value;
|
||||
const T& b = std::any_cast<const T&>(it->second);
|
||||
return a != b;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NameList EnumNames(ToneMapperType v) {
|
||||
static const char* names[] = {"PBR Neutral", "ACES", "ACES Legacy", "Filmic",
|
||||
"Linear"};
|
||||
@@ -104,6 +136,18 @@ struct dependent_false : std::false_type {};
|
||||
template <typename T>
|
||||
bool Ui(std::string_view label, T* value, UiOpts<T> opts = {}) {
|
||||
bool changed = false;
|
||||
bool modified = false;
|
||||
ImGuiID id = ImGui::GetID(label.data());
|
||||
|
||||
if constexpr (std::is_enum_v<T>) {
|
||||
modified = IsModified(id, static_cast<int>(*value));
|
||||
} else {
|
||||
modified = IsModified(id, *value);
|
||||
}
|
||||
|
||||
if (modified) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, kModifiedColor);
|
||||
}
|
||||
|
||||
if constexpr (std::is_enum_v<T>) {
|
||||
int idx = static_cast<int>(*value);
|
||||
@@ -113,64 +157,86 @@ bool Ui(std::string_view label, T* value, UiOpts<T> opts = {}) {
|
||||
} else if constexpr (std::is_same_v<T, bool>) {
|
||||
changed = ImGui::Checkbox(label.data(), value);
|
||||
} else if constexpr (std::is_same_v<T, uint8_t>) {
|
||||
changed = ImGui::InputScalar(label.data(), ImGuiDataType_U8, value);
|
||||
changed = ImGui::DragScalar(label.data(), ImGuiDataType_U8, value, 1.0f);
|
||||
} else if constexpr (std::is_same_v<T, uint16_t>) {
|
||||
changed = ImGui::InputScalar(label.data(), ImGuiDataType_U16, value);
|
||||
changed = ImGui::DragScalar(label.data(), ImGuiDataType_U16, value, 1.0f);
|
||||
} else if constexpr (std::is_same_v<T, uint32_t>) {
|
||||
changed = ImGui::InputScalar(label.data(), ImGuiDataType_U32, value);
|
||||
changed = ImGui::DragScalar(label.data(), ImGuiDataType_U32, value, 1.0f);
|
||||
} else if constexpr (std::is_same_v<T, int>) {
|
||||
if (opts.min.has_value() && opts.max.has_value()) {
|
||||
changed = ImGui::SliderInt(label.data(), value, *opts.min, *opts.max);
|
||||
} else {
|
||||
int step = opts.step.value_or(1);
|
||||
int fast_step = opts.fstep.value_or(100);
|
||||
changed = ImGui::InputInt(label.data(), value, step, fast_step);
|
||||
float speed = opts.step.value_or(1);
|
||||
changed = ImGui::DragInt(label.data(), value, speed);
|
||||
}
|
||||
} else if constexpr (std::is_same_v<T, float>) {
|
||||
if (opts.min.has_value() && opts.max.has_value()) {
|
||||
changed = ImGui::SliderFloat(label.data(), value, *opts.min, *opts.max);
|
||||
changed =
|
||||
ImGui::SliderFloat(label.data(), value, *opts.min, *opts.max, "%.5f");
|
||||
} else {
|
||||
float step = opts.step.value_or(0.f);
|
||||
float fast_step = opts.fstep.value_or(0.f);
|
||||
changed = ImGui::InputFloat(label.data(), value, step, fast_step);
|
||||
float speed = opts.step.value_or(0.01f);
|
||||
changed =
|
||||
ImGui::DragFloat(label.data(), value, speed, 0.0f, 0.0f, "%.5f");
|
||||
}
|
||||
} else if constexpr (std::is_same_v<T, float3>) {
|
||||
changed = ImGui::InputFloat3(label.data(), &value->x);
|
||||
changed =
|
||||
ImGui::DragFloat3(label.data(), &value->x, 0.01f, 0.0f, 0.0f, "%.5f");
|
||||
} else if constexpr (std::is_same_v<T, float4>) {
|
||||
changed = ImGui::InputFloat4(label.data(), &value->x);
|
||||
changed =
|
||||
ImGui::DragFloat4(label.data(), &value->x, 0.01f, 0.0f, 0.0f, "%.5f");
|
||||
} else {
|
||||
static_assert(dependent_false<T>::value, "Unsupported type");
|
||||
}
|
||||
|
||||
if (modified) {
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::SetItemTooltip("RMB to revert change");
|
||||
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
|
||||
if constexpr (std::is_enum_v<T>) {
|
||||
*value = static_cast<T>(std::any_cast<int>(GetInitValues()[id]));
|
||||
} else {
|
||||
*value = std::any_cast<T>(GetInitValues()[id]);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
void DrawAmbientOcclusionGui(SceneView* scene_view) {
|
||||
filament::View* view = scene_view->GetDefaultRenderView();
|
||||
auto opts = view->getAmbientOcclusionOptions();
|
||||
constexpr float PI = std::numbers::pi_v<float>;
|
||||
|
||||
bool changed = false;
|
||||
changed |= Ui("Enabled", &opts.enabled);
|
||||
changed |= Ui("Radius (m)", &opts.radius);
|
||||
changed |= Ui("Power Contrrast", &opts.power);
|
||||
changed |= Ui("Bias (m)", &opts.bias);
|
||||
changed |= Ui("Resolution Scale", &opts.resolution);
|
||||
changed |= Ui("Intensity", &opts.intensity);
|
||||
changed |= Ui("Radius (m)", &opts.radius, {.min = 0.f, .max = 5.f});
|
||||
changed |= Ui("Power Contrrast", &opts.power, {.min = 0.f, .max = 5.f});
|
||||
changed |= Ui("Bias (m)", &opts.bias, {.min = 0.f, .max = .001f});
|
||||
changed |= Ui("Resolution Scale", &opts.resolution, {.min = .5f, .max = 1.f});
|
||||
changed |= Ui("AO Intensity", &opts.intensity, {.min = 0.f, .max = 5.f});
|
||||
changed |= Ui("Bend Normals", &opts.bentNormals);
|
||||
changed |= Ui("Bilateral Threshold", &opts.bilateralThreshold);
|
||||
changed |= Ui("Min. Horizon Angle (Rad)", &opts.minHorizonAngleRad);
|
||||
changed |= Ui("Bilateral Threshold", &opts.bilateralThreshold,
|
||||
{.min = 0.f, .max = 10.f});
|
||||
changed |= Ui("Min. Horizon Angle (Rad)", &opts.minHorizonAngleRad,
|
||||
{.min = 0.f, .max = PI / 2});
|
||||
changed |= Ui("Quality", &opts.quality);
|
||||
changed |= Ui("Low Pass Filter", &opts.lowPassFilter);
|
||||
changed |= Ui("Upsampling", &opts.upsampling);
|
||||
changed |= Ui("SSCT Enabled", &opts.ssct.enabled);
|
||||
changed |= Ui("Cone Angle (Rad)", &opts.ssct.lightConeRad);
|
||||
changed |= Ui("Shadow Distance (m)", &opts.ssct.shadowDistance);
|
||||
changed |= Ui("Max Contact Distance (m)", &opts.ssct.contactDistanceMax);
|
||||
changed |= Ui("Intensity", &opts.ssct.intensity);
|
||||
changed |= Ui("Deeth Bias", &opts.ssct.depthBias);
|
||||
changed |= Ui("Depth Slope Bias", &opts.ssct.depthSlopeBias);
|
||||
changed |= Ui("Sample Count", &opts.ssct.sampleCount);
|
||||
changed |= Ui("Raw Count", &opts.ssct.rayCount);
|
||||
changed |= Ui("Light Direction", &opts.ssct.lightDirection);
|
||||
changed |= Ui("SSCT Cone Angle (Rad)", &opts.ssct.lightConeRad,
|
||||
{.min = 0.0f, .max = PI / 2});
|
||||
changed |= Ui("SSCT Shadow Distance (m)", &opts.ssct.shadowDistance);
|
||||
changed |= Ui("SSCT Max Contact (m)", &opts.ssct.contactDistanceMax);
|
||||
changed |= Ui("SSCT Intensity", &opts.ssct.intensity);
|
||||
changed |= Ui("SSCT Depth Bias", &opts.ssct.depthBias);
|
||||
changed |= Ui("SSCT Depth Slope Bias", &opts.ssct.depthSlopeBias);
|
||||
changed |=
|
||||
Ui("SSCT Sample Count", &opts.ssct.sampleCount, {.min = 1, .max = 255});
|
||||
changed |= Ui("SSCT Ray Count", &opts.ssct.rayCount, {.min = 1, .max = 255});
|
||||
changed |= Ui("SSCT Light Direction", &opts.ssct.lightDirection);
|
||||
|
||||
if (changed) {
|
||||
opts.resolution = (opts.resolution < 0.75f) ? 0.f : 1.0f;
|
||||
@@ -408,7 +474,7 @@ void DrawDepthOfFieldGui(SceneView* scene_view) {
|
||||
changed |= Ui("COC Aspect Ratio", &opts.cocAspectRatio);
|
||||
changed |= Ui("Max COC (Foreground)", &opts.maxForegroundCOC);
|
||||
changed |= Ui("Max COC (Background)", &opts.maxBackgroundCOC);
|
||||
changed |= Ui("Forground Ring Count", &opts.foregroundRingCount);
|
||||
changed |= Ui("Foreground Ring Count", &opts.foregroundRingCount);
|
||||
changed |= Ui("Background Ring Count", &opts.backgroundRingCount);
|
||||
changed |= Ui("Fast Gather Ring Count", &opts.fastGatherRingCount);
|
||||
if (changed) {
|
||||
|
||||
Reference in New Issue
Block a user