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

Implement color profile management (ICC) #903

Open
fire opened this issue May 26, 2020 · 9 comments
Open

Implement color profile management (ICC) #903

fire opened this issue May 26, 2020 · 9 comments

Comments

@fire
Copy link
Member

fire commented May 26, 2020

Describe the project you are working on:
3d multiplayer game project

Describe the problem or limitation you are having in your project:
Rewrote godotengine/godot#26826 as a proposal. Thanks to @toasteater.

Expected: Godot is aware of ICC profiles, and render correctly on wide-gamut displays.
Actual: Godot is not aware of ICC profiles. Colors are distorted and over-saturated.

Many systems (including Windows and X11 platforms) do not have end-to-end color management, and it's up to applications to convert images to device gamuts for display.

Currently, Godot converts all output to sRGB and pushes that directly to the device. The colors are then interpreted as coordinates in the device color gamut, which is usually not exactly sRGB either, but significantly different in case of wide gamut displays. This causes major color distortions, both in the editor and in the exported games.

Describe the feature / enhancement and how it helps to overcome the problem or limitation:

  • Wide gamut displays are commonplace among graphic designers and artists. An accurate representation of colors is critical for their work.
  • Many content creation applications have color correction, so assets would often look different to artists when imported to Godot. This has caused confusion before (e.g. Add support for horizontal scrolling in Tree using mouse buttons (WHEEL_LEFT/WHEEL_RIGHT) #4816, note that one comment's author suggested to turn color management off in the other application, which is totally not a good idea) and will likely continue to.
  • Wide gamut displays are becoming increasingly available to consumers, which means that this affects not only developers, but players as well.

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:

  • Create a ColorRect with a primary color (e.g. ff0000)
  • Observe it on a wide gamut display.
  • Compare output with the output of an ICC aware application with appropriate profiles assigned.

Expected: Same color rendered.
Actual: The color rendered by Godot is much more saturate.

Unfortunately, the effect is much less observable on a normal sRGB-ish display. On my device GIMP renders the sRGB ff0000 as d53b1a, if that puts it into any perspective.

red
(Left: Godot, Right: GIMP w/ ICC profile. Screenshot interpreted as sRGB so the difference can be seen with ordinary displays. The actual saturation difference seen is much greater than what this image suggests.)

While arbitrary gamut conversion can be nice, the most currently needed feature is conversion from sRGB to display gamut, in the editor. One possible way is to allow users to specify an ICC profile in preference, which will be used to generate a 3D LUT texture on load. This resulting texture will then be used to transform the entire editor interface as the last step of rendering. This should suffice for the current use case.

Possible further improvements outside the scope of this feature proposal may include:

  • Loading monitor profiles from desktop environment if available.
  • Support gamut conversion in exported games.
  • Support arbitrary primaries (as opposed to sRGB/Rec709), allowing utilization of consumer wide gamut displays.

It's possible to take LittleCMS (MIT license) on as a dependency for this feature, which I understand won't be a very lightly made decision. ICC profiles are rather complex, so writing one's own parser can be quite slow and error prone. I'm also not experienced with Godot's code base, so I'm seeking feedback before coding anything.

If this enhancement will not be used often, can it be worked around with a few lines of script?:

No. A workaround is possible, but significant work is required:

It's possible to use a custom postprocessing shader and a LUT to convert sRGB (or Linear with sRGB primaries) to whichever color gamut desired. However, custom postprocessing is not currently very wieldy, and it does not apply to UI elements (e.g. color choosers) on the editor side. It's also requires users to somehow generate their own LUTs from ICC profiles.

The Color Correction option in Environment is not fit for this purpose, as it can't be used for 2D, and also conflicts with scene grading within the sRGB gamut.

See godotengine/godot#26869 for a draft in 3.2.

Is there a reason why this should be core and not an add-on in the asset library?:

Changing the rendering pipeline is part of the core.

@ScepticDope
Copy link

Some possible future improvements beyond the scope of this proposal, as previously mentioned here: godotengine/godot#27956

I'd very much like to import some HDR .png files for my game. And be able to toggle HDR on and off on viewports that then start using the correct import version of the PNG.

Also at some point would love a HDR Video Content video format support for the VideoPlayer.

@fire I read your post here: #1004 (comment) The Frostbite engine forces monitors to switch to HDR mode automatically. Even on Windows 8.1 it automatically switched my monitor to HDR, only other application I know of that does that is MadVR. Sadly they are both closed source, besides some very limited information, I have no clue how to go about this specific problem involving HDR.

For Windows it seems to involve sending specific HDR meta data to monitors and exclusive fullscreen somehow and well, that is all I got so far. But that would mean Godot would need to implement that feature first, some references have been made to this issue: godotengine/godot#14542 But there seems to be no actual mention of it specifically there.

Godot's current available OpenGL 3D graphics API's possibly don't actually have a exclusive fullscreen mode. So it might be an idea to wait with more HDR features until the Vulkan build is ready, as Vulkan does support it. I am yet to find if this is a cross platform issue or this exclusive fullscreen is only something specific to Windows to bypass its compositor: https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VK_EXT_full_screen_exclusive

*Something I stumbled upon is that Nvidia and AMD drivers might also create some differences around exclusive fullscreen.

I haven't found a lot of specific info on the HDR meta data you'd need to send over your display signal to the monitor. But I did find this in the Vulkan Specs:
https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#_hdr_metadata

After all this I wondered if a quick and dirty alternative to all this low-level stuff, for Windows 10, could be to simply force the Windows HDR mode to toggle on? I found that someone managed to do exactly that using the Nvidia driver!:
https://github.com/bradgearon/hdr-switch

@fire
Copy link
Member Author

fire commented Feb 16, 2021

@ScepticDope Are you around for a chat? I see your explanation but I don't get it in sufficient detail.

@Calinou Calinou changed the title Color profile management Implement color profile management (ICC) Mar 31, 2021
@ScepticDope
Copy link

@fire Sure, I'll get on Discord soon I think we talked on there before.

@mysterycoconut
Copy link

Currently, Godot converts all output to sRGB and pushes that directly to the device. The colors are then interpreted as coordinates in the device color gamut, which is usually not exactly sRGB either, but significantly different in case of wide gamut displays.

While arbitrary gamut conversion can be nice, the most currently needed feature is conversion from sRGB to display gamut, in the editor.

On the Mac, I solve this by adding the following to the window creation code in platform/osx/os_osx.mm:

[window_object setColorSpace: [NSColorSpace sRGBColorSpace]];

That is enough to signal the OS the window is not in the device's color space, and to have the Window Manager use a shader based color match. Without that line, most Godot games look over-saturated on the "newer" (2015 on) P3 displays.

@MJacred
Copy link

MJacred commented Sep 11, 2022

@fire: Are you still working on this or anyone else? I saw that https://github.com/fire/godot/tree/littlecms and fire/godot@5e9855d have been archived…

@fire
Copy link
Member Author

fire commented Sep 12, 2022

It is salvagable, I am not directly working on this.

@ScepticDope
Copy link

ScepticDope commented Jan 5, 2023

Speculation, but with HDR maybe being a cool new feature on the new Steam Decks or part of Proton, @Plagman? HDR on Linux might get a little push. And thus it might start to be more of interest to Godot developers as well?:
https://twitter.com/Plagman2/status/1610200412854046720

Also found this nice up to date overview on HDR on Linux's current state of affairs:
https://wiki.archlinux.org/title/HDR_video_playback

@fire
Copy link
Member Author

fire commented Nov 19, 2023

The steam deck oled launched a few days ago. This means the Linux operating systems should have a way to test oleds and be related to gaming.

@Calinou
Copy link
Member

Calinou commented Nov 20, 2023

The steam deck oled launched a few days ago. This means the Linux operating systems should have a way to test oleds and be related to gaming.

Wayland/Gamescope indeed have basic HDR support (and Plasma 6 will support it officially), but NVIDIA support is still missing. Only AMD and Intel GPUs currently support HDR on Linux.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants