ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
57.7k stars 9.9k forks source link

HDR Support? #7036

Open harrisbb opened 7 months ago

harrisbb commented 7 months ago

Version: 1.90 (WIP) Branch: master Back-ends: imgui_impl_sdl2.cpp + imgui_impl_vulkan.cpp Operating System: Windows 11

Hello! First of all I am wondering if and how others have dealt with HDR surface formats. With above configuration I get very washed-out/incorrect colors if I use a Vulkan HDR surface format (e.g. vk::ColorSpaceKHR::eExtendedSrgbLinearEXT) for my backing swapchain. As far as I know this is entirely expected - HDR often has bad interactions with GUI libraries and requires explicit corrections (which are needed for other rendering as well). I attempted to scale all the ImGui style colors up directly but they appeared to still be clamped (<= 1.0) when arriving in the backend fragment shader and the extended format needs larger values (> 1.0) to appear correct. Has anyone come up with direct/easy solutions without modifying ImGui?

For now I have successfully added rudimentary HDR support in my local version of imgui_impl_vulkan.cpp. The change is very small - essentially I just pass color scaling and gamma exponent uniforms to the backend fragment shader. This enables the user to apply global color correction factors as they wish. The other changes are just piping those additional uniforms from ImGui_ImplVulkan_RenderDrawData on down. This solution is more general than HDR but also not really a correct color-space conversion (just a practically sufficient approximation)?

For reference here is my modified backends/vulkan/glsl_shader.frag (can provide more complete patch if needed):

#version 450 core
layout(location = 0) out vec4 fColor;

layout(push_constant) uniform uPushConstant {
    vec2 uScale;
    vec2 uTranslate;
    float colorGamma;
    float colorScale;
} pc;

layout(set=0, binding=0) uniform sampler2D sTexture;

layout(location = 0) in struct {
    vec4 Color;
    vec2 UV;
} In;

void main()
{
    const vec4 color = In.Color * texture(sTexture, In.UV.st);
    const vec3 colorTgt = pow(color.rgb, vec3(pc.colorGamma)) * pc.colorScale;
    fColor = vec4(colorTgt, color.a);
}
pthom commented 5 months ago

Hello,

For information only, I have worked on a similar subject, using the Metal backend. I was able to use EDR (Extended Dynamic Range) on macOS, from inside a library on top of ImGui. See this PR. In this case, it did not require shader adaptations, only to change the Metal setup code:

caMetalLayer.pixelFormat = MTLPixelFormatRGBA16Float;
meshula commented 5 months ago

I've got a fully worked solution on Metal. In order to get textures working properly and color managed all the way through was ... a lot of work .... Beyond the set up @pthom mentions there's work that needs doing on on the NSView, and also shader tweaks. I would love to have the equivalent for Vulkan & DX, but haven't had time to even start thinking about it yet. You'll have to believe me that the image below is EDR, with a DisplayP3 color gamut :)

image