-
-
Notifications
You must be signed in to change notification settings - Fork 23.3k
[WIP Prototype] Add HDR support to tonemappers #106696
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
base: master
Are you sure you want to change the base?
Conversation
Makes me think we should take a little time to ponder about supporting HDR color pickers. Such as suggests this proposal: godotengine/godot-proposals#1031 |
I tried this PR out with Crater-Province-Level, and took some HDR screenshots, then took some SDR screenshots for comparison. I can't speak to the quality quite yet because I just borrowed the living room LG C3 to take these shots, and that TV isn't calibrated for accuracy or neutrality - it had auto tonemapping and over saturated colors and all that. What I will say is - it works - and it looked ****ing amazing on the big TV. 😆 I'm linking a public Google Drive folder that contains the screenshots because the folder is too big to upload to Github. (148 MB. HDR screenshots are massive! And these are only 1080p!) I recommend downloading the folder locally to your computer, and opening the files with the built in Windows image viewer. Of course, make sure HDR is enabled in the settings. The HDR screenshots are in JPEG XR format (.jxr) and the SDR screenshots are in PNG format. https://drive.google.com/drive/folders/1roqSMTxdNaFINImqaxk_ReQAqtpUrz0n?usp=drive_link |
Hi @allenwp, I've gone ahead and tried out your PR to see how HDR is working on my Windows 11 PC. I don't have a personal 3D project going on, so I'm just using the opening scene of the TPS demo for testing. I've taken some screenshots on an ASUS PG27AQDM OLED monitor, using the "Console HDR Mode", using the Nvidia App to take the screenshots, and setting the SDR content brightness in the Windows settings to 14. I haven't yet added a tonemap to the Camera3D node. Here is the link. To explain the three screenshots:
When viewing through the Windows Photos app via the OLED monitor, only As was pointed out in the other PR thread, I can't get these screenshots to perfectly align in colors and brightness when viewing in SDR. Leaving aside My assumption is that the tonemap timeline of
Whereas
If so, I wouldn't rule out the possibility that the Windows Photos app might be altering the colors that's totally outside our control. To be honest, I'm not sure if it's feasible for the "double tonemap" that's occurring with |
Looks like I made a big oopsie and took those screenshots while RTX HDR was enabled globally. So the screenshots are not accurate for a baseline HDR setup. I’ll rename the folder above to fix this error. In my spare time, I’ll redo the screenshots with RTX HDR disabled. Since this PR is focused on the tonemappers, I’ll go ahead and test Linear and AgX specifically. |
Cool, thanks @iuymatiao! I honestly haven't tried many approaches for taking screenshots and videos yet, so I can't even comment on whether the process is beneficial. In the end, it is most important that you get consistent behaviour between SDR and HDR modes with the only difference being that the brightest parts of the scene appear brighter in HDR mode. This naturally brings a higher contrast and vibrancy to the image in HDR mode as a side-effect. Importantly, you should notice that scenes that have no bright values (underexposed scenes) should be identical between HDR and SDR. This is important to aid developers in being able to easily and quickly author content that is consistent between the two output modes, with HDR simply taking advantage of the higher brightness that is available. |
OK. Here is Round 2. This time, RTX HDR has remained disabled globally. The link to the new screenshots can be found here. Folders are split between the Linear and AgX tonemappers. Describing each file:
Note that I'm using the 'Use Screen Luminance' setting in Project Settings, and SDR Content Brightness in Windows 11 is set to 14. Unfortunately, for some reason, the peak brightness seems to be unchanged over SDR. For what it's worth, the Nvidia App did recognize that HDR was enabled in the project, hence why With that said, I did find some interesting observations. When viewed on my HDR monitor, with the Linear tonemapper, I'm not sure what to make of these findings. Right now, I can't get HDR to explicitly appear unless I use Nvidia's RTX HDR feature (and keep Project Settings HDR disabled). Not sure how @Jamsers got it working, but it might be worth double-checking if RTX HDR was globally enabled there as well. If there's a silver lining, the fact that RTX HDR stopped functioning as soon as Project Settings HDR was enabled probably means that RTX HDR recognized a native HDR implementation and "stepped aside". If so, that means it's just a matter of getting peak luminance to work properly. I'll probably need to find another Godot project to test to make sure I get a fuller picture. |
Hi @iuymatiao, for me, I had to use Godot's DX12 driver to get HDR working, HDR didn't seem to work when using Godot's default Vulkan driver. This can be changed in However, my own builds of this branch didn't have DX12 working, because IIRC you need to do some Windows SDK specific stuff to have DX12 working with Godot. So I used the build from the CI artifacts from allenwp's branch. (the latest one as of this comment can be found here, just scroll down and download the I think HDR isn't working on Vulkan on Windows yet because for Vulkan on Windows, I think you need a DXGI swapchain for HDR to work, and there isn't any progress on that front. Apart from changing the tonemapper of my project from ACES to AgX, enabling Windows HDR, and enabling Godot HDR, I kept everything else at default. |
Another thing to note may be that differences between HDR and SDR for my project (Crater-Province-Level) might be a lot more significant compared to other Godot projects because I use physical light units in that project and stick to as close to reference values for all light brightness. That means that, at noon for example, you could be getting as much as 100,000 lux outdoors, while only getting 1,000 lux indoors. Such an extreme differential in luminosity lends itself well to HDR, as you can imagine. |
I've created an SDR-only PR that implements a number of the elements from this prototype PR: #106940 |
Edit: I wrote this wrong initially, I meant to say: For linear, the SDR, HDR disabled, and HDR enabled screenshots should look the basically same regarding all values that are less than ...But dark colours are more vibrant in the HDR version than in the SDR version, so maybe taking screenshots isn't working quite right. Or it's something in else the environment effects. I suspect I'll need to look more into screenshot capture to see if there's a stable way to capture output. I also plan to make a little test scene for HDR output. I'll do this sometime in the next couple of weeks, likely. Thanks for checking this out! |
For those interested, I've made a blog post that has videos of how the new Adjustable tonemapper works: https://allenwp.com/blog/2025/05/29/allenwp-tonemapping-curve/ |
Just wanted to provide a quick update that I was able to get an HDR output when using @Jamsers's Crater Province project. So the existing Godot demo projects really aren't built to push max luminance at the moment. |
b67a60a
to
69b54d2
Compare
69b54d2
to
c7f8582
Compare
c7f8582
to
275a57c
Compare
Co-authored-by: Alvin Wong <[email protected]> Co-authored-by: Allen Pestaluky <[email protected]>
Fixed negative numbers created by black parameter. Updated HDR tonemappers to include udpates from godotengine#106940 This is a CIE correct way of doing a "black" tonemapper parameter. Attempt at optimization of the curve function Changed minimum white parameter for AgX to be 1.0, just like the Adjustable tonemapper. Added docs for new tonemapping parameters. Fixed unused variable error Spattered my domain over the code to direct LLM AI users to the blog post I'm working on Removed brightness tonemap parameter: this is artistic control is better expressed with exposure and contrast. Added an "Adjustable" tonemapper Added user controls for AgX HDR and black parameter for all tonemappers HDR AgX (first pass) Re-do tonemappers for HDR support (AgX HDR, Reinhard HDR, and a new curve...)
275a57c
to
9103ac7
Compare
Very cool – tried the HDR video on my MacBook Pro display, and it looks awesome. |
…an get any faster than this.
This prototype demonstrates how tonemappers could behave when HDR output is enabled. Please provide feedback in the comments! You can use Windows Game bar to take HDR screenshots OBS Studio has good support for HDR video recording as well (let me know if you want me to give you OBS configuration details).
This branch builds on top of #94496. Please share any feedback relating to HDR (not tonemappers) on that PR instead! Many of the changes from this PR should be merged in a separate PR, as these changes include adding
white
parameter support to the AgX tonemapper, which is required independently of HDR output support.This draft PR implements godotengine/godot-proposals#12317, including the addition of two new tonemaping user parameters:
black
andcontrast
, both of which I feel are required for flexible and stable HDR output behaviour. Please review this proposal for rationale.Importantly, Flimic and ACES tonemappers cannot support HDR output. This is because the
white
parameter of these tonemappers was designed exclusively for SDR and this style of white parameter cannot work with HDR and variable Extended Dynamic Range (EDR). This PR demonstrates how they should behave in HDR mode: exactly the same as they behave in SDR mode, limited to [0.0, 1.0] range.Because Filmic cannot support HDR mode, I have introduced a new tonemapper that is HDR-compatible to replace it: the Adjustable tonemapper. Unlike AgX, this tonemapper does not desaturate colours to white as they become very bright and applies the tone curve directly in the linear sRGB working colour space, just like Filmic does. It's configuration parameters match AgX and it can be configured to appear similar to Filmic in SDR.
Check out videos of how this new "Adjustable" tonemapping curve works on my blog post.
On a related note, the new configuration parameters of AgX (specifically
contrast
) can be used to make it appear similar to ACES, but with correct HDR output support.Usage
Download windows-editor Artifact from the Checks page of my branch.
The basics of tonemapping in Godot is covered in the docs. In this PR I've updated the in-engine docs to have some more detail.
HDR output is covered in detail in the original PR #94496, but here's a quick summary:
rendering/viewport/hdr_2d
display/window/hdr/enabled
To control HDR brightness settings:
Option 1: Simply change the SDR content brightness in Windows (you might need to move or resize the Godot window to force it to refresh):

Option 2: Disable
display/window/hdr/use_screen_luminance
and manually set the Reference Luminance (this is equivalent to SDR content brightness) and Max Luminance.Note: Reducing the max luminance with Option 2 may be necessary to circumvent the built-in tonemapping of your display.
Performance
Performance of the AgX tonemapper is better than the current implementation in
master
. I wasn't able to get as good of performance as my best attempt using Timothy Lottes' curve in #102435, but the stability and predictability of the curve in this PR across all of variable EDR is a reasonable trade off that gives a significantly better user experience when targeting both SDR and HDR.A number of additional parameters are now passed from the CPU to the GPU, increasing the number of bytes passed into the tonemapper. This has a minor impact on performance (barely measurable on my NVIDIA 980 Ti for a 4K window). Unfortunately, this affects all tonemappers... which leads me to my next point:
Adding another tonemapper to Godot, as it is currently implemented, causes a notable performance degradation to all tonemappers. This happened in Godot 4.4 when AgX was added to Godot, and it will happen again when the new Adjustable tonemapper is added. Work needs to be done to address this at a structural level.
The
black
parameter makes ALL tonemapping notably slower. I haven't looked into how this can be optimized yet; this PR simply demonstrates how it should look when it is correctly implemented.Limitations
Known Issues
white
is less than 1.0 and HDR has been enabled. The code currently checks to see ifmax_value != 1.0
instead of checking if HDR is enabled, but this is incorrect becausemax_value
can equal1.0
when HDR is enabled andreference_luminance == max_luminance
.