Skip to content

Conversation

@allenwp
Copy link
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.
  • 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

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
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!

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.

3 participants