Skip to content

[DRAFT] Add HDR output demo#1287

Draft
allenwp wants to merge 28 commits intogodotengine:masterfrom
allenwp:hdr-output-demo
Draft

[DRAFT] Add HDR output demo#1287
allenwp wants to merge 28 commits intogodotengine:masterfrom
allenwp:hdr-output-demo

Conversation

@allenwp
Copy link
Copy Markdown
Contributor

@allenwp allenwp commented Dec 19, 2025

HDR output is planned for Godot 4.7. Along with its release, we should provide an official demo project. This PR is my attempt at this sort of a demo project.

Please use the build artifacts from the HDR output PR to test this demo.

Overview

image

I recommend trying out this demo yourself. My hope is that you will learn some things along the way. Regardless, I'll go over some of my rationale for different elements I've included in the project:

  1. Player-facing in-game settings
    • This is a packed scene that the developer can copy into their project that is suitable for presentation to players.
    • Saving and loading of settings is included. Developer settings are provided to delete the saved settings.
    • These settings also allow the developer to see how changing HDR brightness (aka reference white luminance) and Max luminance affects different scenes.
  2. Reference monitor calibration
    • This is a simple, but fairly effective tool for calibrating the correct max luminance value for a developer's screen.
    • Unlike many calibration tools built into operating systems (like the Windows HDR calibration app), this tool also presents Rec. 709 primary colours to help the developer discover when their display's internal tonemapping kicks in.
  3. Debug information
    • The DisplayServer, RenderingDevice, and Window support for HDR is printed on the screen for debugging why HDR might not be available for the user.
    • Black, White, and Max luminance are shown alongside their linear relative luminance (scene) values.

Demo scenes

output_max_linear_value

image

This scene demonstrates how to use the Window.output_max_linear_value. This could be 2D or 3D, although I currently have only 2D nodes. The important part is that no WorldEnvironment is used in this scene.

Environment

image

This scene demonstrates how to use a WorldEnvironment with the AgX tonemapper to produce HDR visuals. There is a lot of potential to make something that looks pretty cool here.

Color sweep

image

The colour sweep scene presents a full range of saturated colours and a greyscale band with tick marks showing linear values as well as sliders to control the min and max. Min and max are presented in exposure stops relative to reference white. The output_max_linear_value is shown as a tick mark on the chart that moves as max luminance is adjusted.

Setup instructions

image

This final scene outlines the full set of steps that must be followed to enabled HDR output on a project. I have kept this as the last scene on the list so that people can see the fancy visuals first before diving into the technical details of how to implement HDR in their project.

Remaining work

  • Better visuals for output_max_linear_value demo scene.
  • Better visuals for Environment scene.
  • Code cleanup.
  • Change colour sweep scene's tooltip background colour to opaque
  • Add a link to Godot manual page on HDR output (maybe put the link at the bottom of the setup instructions).
  • Remove exposure stop numbers entirely from colour sweep scene. Instead, have linear value as main value and nits in parentheses.
  • Add tooltip to colour sweep that explains tick marks.
    • "The upper tick mark indicates output_max_linear_value. The lower tick marks are log base 10 scale with the rightmost white tick mark indicating 0.1."

@iuymatiao
Copy link
Copy Markdown

I tried out the demo project, and here are my first impressions:

Calibration

Is there a reason why we no longer ask users to adjust the slider until the triangle has completely faded? I always thought that was a more intuitive way to go about HDR calibration.

Setup Instructions

I think the "Setup Instructions" page should go first. If we're worried that the project won't show any HDR on first-open, we can add a "Begin Demo" button at the bottom of the instructions to show that the actual HDR demo is on the next page.

output_max_linear_value

The demo does a good job of showing how max linear value changes as luminance values are updated, However, it's not obvious to me how I should be using this linear value from a content mastering perspective.

Assuming the sun and particle effects are programmatically tied to the max linear value, I think the demo can show debug information showing that these elements are dynamically changing brightness based on max linear value, while other elements retain static (hardcoded?) linear values by comparison. Maybe we can show those linear values as annotations on top of the scene element for a more stylized presentation.

This can help teach developers that only specific elements of the game scene should use dynamic linear values, enforcing the EDR paradigm.

Environment

This is more of a wishlist feedback, but I would love to get a built-in "HDR Heatmap" that viewers can toggle, so that they can see which parts of a 3D scene actually exceed SDR levels of brightness. Something like this:

image

The heatmap could also give developers an idea of what nit values they should be feeding into their 3D game elements for a good tonemapped HDR scene.

Color sweep

It would be nice to explain why the linear values are set to a Min of -14.00 and a Max of +5.00. Is this to deliberately show dark and bright clipping for demonstration purposes? I think the Min and Max sliders should have a reset button so that developers don't "break" the scene and require a full restart.

The tick marks are also difficult to understand for someone just getting started on HDR. I think it would be a good idea to show a tooltip upon clicking/hovering on these tick marks to show what the linear, stop and nit values are at that point in the x-axis.

@allenwp
Copy link
Copy Markdown
Contributor Author

allenwp commented Jan 6, 2026

Thanks for taking the time to try it out and provide feedback @iuymatiao! This is very appreciated and helpful!

Is there a reason why we no longer ask users to adjust the slider until the triangle has completely faded? I always thought that was a more intuitive way to go about HDR calibration.

I agree, the old approach was better. Unfortunately, it is no longer possible due to clipping to ouput_max_linear_value in the blit.glsl shader. I believe that this developer calibration image is not important enough to provide an option to the developer to disable this clipping; many platforms (like the Windows HDR calibration tool) provide a calibration image that is similar to the old approach I used anyway.

I think the "Setup Instructions" page should go first.

I opted to put the setup instructions as the last page because the primary goal of this project is to demonstrate the HDR output feature, rather than explain how to enable it in your own project. I could simply remove these setup instructions entirely, which would give a sharper focus to the project being only a demo, but I don't think there is harm in including them. The manual page will be the primary source for setup instructions, as it provides additional information on how to correctly use the feature. I've added a link to the manual page on the setup instructions of this demo.

Let me know if there are any specific reasons you believe it should be the first view that is shown when starting the project, even with the above rationale in mind.

output_max_linear_value

The demo does a good job of showing how max linear value changes as luminance values are updated, However, it's not obvious to me how I should be using this linear value from a content mastering perspective.

Assuming the sun and particle effects are programmatically tied to the max linear value, I think the demo can show debug information showing that these elements are dynamically changing brightness based on max linear value, while other elements retain static (hardcoded?) linear values by comparison. Maybe we can show those linear values as annotations on top of the scene element for a more stylized presentation.

This can help teach developers that only specific elements of the game scene should use dynamic linear values, enforcing the EDR paradigm.

Good points. I now realize that it would probably be a good idea to have a limit on some things, like the sun, to show that it is sometimes a good idea to not just blindly trust the output_max_linear_value, but maybe only go up to as bright as 5.0 or 10.0. I've added that to the scripts and examples.

I'm going to need to think a bit more about how to display more information about these. Maybe a tooltip is best... There is a LOT on the screen for a new user and I don't want to overwhelm with too many numbers and text. The output_max_linear_value is always shown at the top of the screen ("Max"), so maybe the rest is best in tooltips.

This is more of a wishlist feedback, but I would love to get a built-in "HDR Heatmap" that viewers can toggle, so that they can see which parts of a 3D scene actually exceed SDR levels of brightness.

I think this sounds like something that would be better as a feature in the Godot editor, rather than this demo project?

It would be nice to explain why the linear values are set to a Min of -14.00 and a Max of +5.00. Is this to deliberately show dark and bright clipping for demonstration purposes? I think the Min and Max sliders should have a reset button so that developers don't "break" the scene and require a full restart.

Ah, thanks for bringing my attention to the exposure stop labels! In my porting project, I use exposure stops quite heavily, but it doesn't make sense to have them at all in this project. I've removed the exposure stops entirely.

The default min and max values are pretty arbitrary: they are intended to show the difference of very dark and very bright colours between SDR and HDR, but the exact numbers don't matter. I'm hesitant to add a reset button because these default values are very arbitrary.

The tick marks are also difficult to understand for someone just getting started on HDR. I think it would be a good idea to show a tooltip upon clicking/hovering on these tick marks to show what the linear, stop and nit values are at that point in the x-axis.

Good idea, I've added a tooltip that explains the tick marks.

Thanks again!

Copy link
Copy Markdown
Member

@AThousandShips AThousandShips left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also all "colour" needs to be changed to "color"

@AThousandShips
Copy link
Copy Markdown
Member

Please use the batch commit feature to add all changes at once (to avoid lots of pings)

@allenwp
Copy link
Copy Markdown
Contributor Author

allenwp commented Feb 3, 2026

Please use the batch commit feature to add all changes at once (to avoid lots of pings)

I just discovered this feature as you were writing your message!

allenwp and others added 4 commits February 3, 2026 10:50
Co-authored-by: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com>
@allenwp
Copy link
Copy Markdown
Contributor Author

allenwp commented Feb 3, 2026

Thanks for your help with this AThousandShips!! I'm pretty slammed, so the assistance with the code cleanup is appreciated :)

Ensure no Environment resources use SDR-only features

I struggled a fair bit with this sentence and I like the wording you suggested in your review. Thanks! I also had no idea that macOS was branded as "macOS" 😅

@AThousandShips
Copy link
Copy Markdown
Member

Negation is a nightmare to write!

@iuymatiao
Copy link
Copy Markdown

Is it possible to provide a dedicated tooltip for each tick mark, displaying their current values? It would go a long way to minimize confusion as to what’s being measured on the screen, IMO.

@allenwp
Copy link
Copy Markdown
Contributor Author

allenwp commented Feb 14, 2026

Maybe even better would just be the linear value at the cursor’s horizontal location that pops up and is always visible when mousing over any part of the colour sweep?

(To be honest, though, it might take an extra week or two or five for me to have the small amount of time I need implement this, so maybe it can be added as an improvement after this is merged.)

@iuymatiao
Copy link
Copy Markdown

Maybe even better would just be the linear value at the cursor’s horizontal location that pops up and is always visible when mousing over any part of the colour sweep?

That would probably be the best possible implementation if it's trivial to add.

if not DisplayServer.has_feature(DisplayServer.FEATURE_HDR_OUTPUT):
tooltip_text = "Display Server does not support\nHDR output. This usually means\nthat Godot does not support HDR\noutput on your current platform,\nbut other Display Server drivers may support HDR output.\n\n"
elif not device_has_hdr:
tooltip_text = "Rendering Device does not support\nHDR output. Try changing the\nRendering Device driver in your\nproject settings to a driver that supports\nHDR output, such as d3d12 for Windows\nand metal for macOS.\n\n"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should D3D12 and Metal get their "branding names"?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure -- I wrote them as they're seen in the Project Settings window, given that's what the user is being instructed to change.

allenwp and others added 2 commits March 18, 2026 09:09
Co-authored-by: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com>
- Improve Output Max Linear Value scenes (add 2D and 3D test cases).
- Add a 3D scene that showcases HDR output and environment glow.
- Add a project icon and README.
- Move to `misc/` to avoid additional top-level folder.
- Improve SubViewport quality using SSAA on top of MSAA.
- Enable low-processor mode to reduce CPU/GPU utilization when idle.
  - Ensure all scenes are stills to avoid continuous redrawing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants