Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correct color on wide-gamut displays #2712

Open
elliottslaughter opened this issue Feb 10, 2023 · 5 comments
Open

Correct color on wide-gamut displays #2712

elliottslaughter opened this issue Feb 10, 2023 · 5 comments
Labels
eframe Relates to epi and eframe feature New feature or request

Comments

@elliottslaughter
Copy link

Some displays support color gamuts larger than sRGB. E.g., many recent Mac laptops use the Display P3 color space. As best I can tell, egui/eframe naively assume the display's color gamut is sRGB, and this causes colors to be drawn incorrectly on devices with wider gamuts.

The easiest way to test this to set up a comparison with a web browser. Safari and Firefox are both gamut-aware and will correctly draw colors in sRGB when viewed on a wide-gamut display. Note that the display-p3 syntax is specific to Safari:

<html>
<head>
<style>
body {
    /* sRGB: renders correctly in Firefox and Safari */
    background-color: steelblue;
    /* this is equivalent in rgb(...) notation: */
    /* background-color: rgb(70, 130, 180); */

    /* Display P3: requires Safari */
    /* background-color: color(display-p3 0.27450980392156865 0.5098039215686274 0.7058823529411765); */
}
</style>
</head>
<body>
</body>
</html>

For comparison, you can set up a simple app with eframe_template and draw a rect with Color32::from_rgb(70, 130, 180). Note that the color that is shown matches the Display P3 color test, not sRGB.

In contrast, when I run the same eframe_template app via trunk and open it in Firefox, the colors are rendered correctly. It must be that Firefox performs color correction in WebGL contexts and ensures that sRGB colors are displayed correctly.

@elliottslaughter elliottslaughter added the feature New feature or request label Feb 10, 2023
@emilk emilk added the eframe Relates to epi and eframe label Feb 10, 2023
@emilk
Copy link
Owner

emilk commented Feb 10, 2023

Interesting!

Do you know anyone with a wide-gamut display that can help fix this? :)

@elliottslaughter
Copy link
Author

I have a wide-gamut display, but I'm not sure how I'd go about a fix.

I assume that pushing gamut support all the way through egui/eframe would be a huge amount of work and not necessarily desirable.

But if there's a way to, say, set up the OpenGL context (or whatever backend we use these days) to use sRGB, maybe there's a simpler fix that wouldn't involve too much churn. We could perhaps put it behind a flag/setting so that interested users could still access Display P3 colors if they wanted to. But it would make it so that for everyone else, things would render more consistently across platforms. The fact that egui with WebGL already works this way makes me hopeful that it's maybe not too much work. But even so, I really don't know where to start.

@bancek
Copy link

bancek commented Jun 28, 2023

On macOS Ventura (13.4), Wgpu renderer and web (Chrome 114) produce correct colors. Glow produces too bright colors. Using Wgpu solves this for me.

Wgpu:

egui-wgpu

Glow:

egui-glow

web (Chrome):

egui-web

Code from Android docs:

std::vector<EGLint> attributes;
attributes.push_back(EGL_GL_COLORSPACE_KHR);
attributes.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_EXT);
attributes.push_back(EGL_NONE);
engine->surface_ = eglCreateWindowSurface(
    engine->display_, config, engine->app->window, attributes.data());

This would probably need to be done in eframe where gl_surface is built:

let surface_attributes =
    glutin::surface::SurfaceAttributesBuilder::<glutin::surface::WindowSurface>::new()
        .build(window.raw_window_handle(), width, height);

let gl_surface = unsafe {
    self.gl_config
        .display()
        .create_window_surface(&self.gl_config, &surface_attributes)?
};

Although by looking in glutin sources, cgl_backend is used on macOS and surface_attributes are ignored altogether and raw_window_handle is used.

@virtualritz
Copy link

virtualritz commented Oct 7, 2024

On this note: the docs do not say what color space the linear RGB (color model) used in egui::Rgba is. "Linear RGB" is pretty meaninless w/o this information.

Working on an app that needs to display images and stuff like e.g. color swatches 'correctly' (the RGB color is e.g. in linear ACEScg). My assumption is that this is simply treated as linear sRGB (i.e. sRGB primaries but no gamma-encoding). I.e. egui will just apply the gamma-encoding when converting these to 8bit/channel for display. Is this correct?

P.S.: I'd be interested in hearing if there is any new insights on this issue by anyone since the last comment?

@Wumpf
Copy link
Collaborator

Wumpf commented Oct 23, 2024

The way egui::Rgba is used across egui implies it's Bt.709/sRGB primaries prior to OETF, i.e. in optically linear units. That, paired with the fact that egui always assumes 8bit sRGB output (post-OETF, i.e. "with applied gamma") means that your conclusion is correct :)
That this is not speced properly can be regarded as a bug that needs fixing!

no movement on the general issue. Color is particularly cursed on WebGL, and nothing has been done yet to support P3 and other output formats.
I think in a nutshell what I think needs to happen to move this forward, is that egui's rendering backends (each individually!) need to take those Bt.709 floating point linear colors that and then apply the correct color-space-conversion + OETF (both!) depending on the expected output. Since egui has only a single shader, it should be realtively straight forward to do this entirely in software which limits exposure to the more cumbersome (and error prone!) automatic driver sided conversions like EGL_GL_COLORSPACE_KHR.
Btw. that's already the preferred mode of operation in egui. This comes mostly from the fact egui wants to do blending in a more perceptual space, for details see this older pr.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
eframe Relates to epi and eframe feature New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants