Introduction
HDR, Emission, Bloom, Exposure, and Tonemapping are related but different features. Player Settings adds another: HDR Display Output.
Separate brightness during rendering from HDR display output, using an SDR-monitor experiment, diagnostics, and custom-rendering examples.
Sections 1–5 cover internal HDR; 6–8 cover output. Skip advanced sections 9–10 for troubleshooting in section 11 as needed.
Scope: Unity 6.3 LTS (6000.3), URP 17.3, English UI. Documentation review date recorded in the Japanese source: September 15, 2026. This translation does not revalidate every reference.1
Untested examples: Unity compilation, scene execution, Player builds, HDR-display testing, and benchmarking have not been performed for this article. Observation prompts are not measured results.
1. Two meanings of HDR
HDR means High Dynamic Range. In Unity, distinguish these two uses:2
| HDR rendering | HDR display output | |
|---|---|---|
| Purpose | Preserve brightness during rendering | Use an HDR display path |
| Controls | Camera, shader, buffer, post-processing | Player, OS, GPU, display |
| HDR monitor? | Not for internal processing | Yes, with compatible output |
HDR rendering can end in SDR output. Games for SDR monitors can preserve HDR internally and map it to the display range afterward.2
High Definition Render Pipeline (HDRP) is not required for HDR. URP supports it, and HDRP also needs output configuration.34
2. Why values above 1 matter
A white wall is not an emissive sign
These grayscale shader outputs illustrate scene values, not measured luminance:
White surface: ( 1, 1, 1)
Emissive surface: ( 4, 4, 4)
Strong emission: (16, 16, 16)
Clamping them to 0–1 makes all three (1, 1, 1). Later processing cannot recover the difference.
An HDR buffer preserves differences for Bloom and later output conversion. HDR retains information; it does not simply brighten the image.2
Tone mapping is not clipping
Tone mapping remaps brightness to the output range. For example:
y = x / (1 + x)
| Input x | Clamped to 0–1 | Result of the formula |
|---|---|---|
| 1 | 1 | 0.500 |
| 4 | 1 | 0.800 |
| 16 | 1 | 0.941 |
This preserves differences within 0–1. It is not Unity's Neutral or ACES formula. Choose URP's operator in the Tonemapping Volume Override.5
3. Linear, HDR, gamut, and bit depth
| Concept | What it describes |
|---|---|
| Linear / Gamma | How lighting and color values relate numerically |
| HDR / SDR | Brightness range |
| Color gamut | Represented/encoded color range |
| Bit depth / format | Precision and numerical range |
Linear does not enable HDR output. 10-bit storage need not be HDR, and HDR does not make assets wide-gamut.67
Set Project Settings > Player > Other Settings > Rendering > Color Space to Linear. This changes lighting and blending in existing Gamma projects; compare and readjust their appearance.89
Do not disable sRGB (Color Texture) everywhere. Color textures and data masks differ. Disabling it skips sRGB-to-Linear sampling conversion; choose according to the data.10
4. Compare HDR on an SDR monitor
Disable HDR display output initially to isolate internal HDR from OS/display settings.
4.1 Check the active URP Asset
An asset assigned to the current Quality level overrides the default. Identify the active asset with GraphicsSettings.currentRenderPipeline.11
Enable its HDR setting and set Post-processing > Grading Mode to High Dynamic Range. Grading Mode controls grading, not display output.12
4.2 Configure the camera and Volume
Use one Base Camera without a target RenderTexture. Enable Output > HDR Rendering and Rendering > Post Processing in its Inspector.13
Create GameObject > Volume > Global Volume with a new Profile and Weight 1. Include its Layer in the camera's Volume Mask. Disable other Volumes and custom Renderer Features.1413
Add Bloom and Tonemapping. Enable each edited setting's override checkbox:
| Override | Setting | Comparison value |
|---|---|---|
| Bloom | Threshold | 2.0 |
| Bloom | Intensity | 0.5 |
| Bloom | Scatter | 0.7 |
| Tonemapping | Mode | None initially |
These are examples, not defaults or universal recommendations. Leave other color/exposure adjustments off.
Bloom Threshold uses gamma-space brightness. Threshold 2 does not directly select Linear shader values above 2.15
URP includes Volume-based post-processing; do not mix in Post Processing Stack v2.16
4.3 Build an HDR Unlit Shader Graph
Create a Universal Unlit Shader Graph to avoid lighting effects. Expose a Color property named HDR Color, Mode HDR, connected to Fragment Base Color. Keep Surface Type Opaque.1718
HDR Color property
Mode: HDR
|
+-- Fragment / Base Color
Create three materials, with Alpha 1. Enter RGB using the HDR picker's float display:
| Material | RGB | Intensity from white |
|---|---|---|
| A | (1, 1, 1) | 0 |
| B | (4, 4, 4) | +2 |
| C | (16, 16, 16) | +4 |
Each Intensity step doubles RGB: +2 means ×4, +4 means ×16—not ×4. Reopening the picker can change its color/intensity decomposition without changing stored RGB.19
Assign A, B, C to Cubes at (-1.5, 0, 0), (0, 0, 0), (1.5, 0, 0). Use camera position (0, 0, -6), rotation (0, 0, 0), Orthographic Size 2, a dark solid background, and 16:9 Game View.
4.4 Change one variable at a time
These are observation prompts, not results recorded in Unity:
| Configuration (Bloom values are Intensity) | What to examine |
|---|---|
| HDR on, Bloom 0, Tonemapping None | Does SDR hide differences in the white surfaces? |
| HDR on, Bloom 0.5, Tonemapping None | Do similar whites produce different glow? |
| HDR on, Bloom on, Neutral | How do highlights and surroundings change? |
| Same setup, HDR Rendering off | How does losing HDR differences affect Bloom? |
Look for different values behind apparently identical whites, not just glow.
Bloom also works on 0–1 images with a low Threshold. HDR distinguishes brighter-than-white values.15
5. Separate Emission, Bloom, exposure, and tone mapping
This conceptual flow is not an exact render-pass schedule:22021
Shaders and lighting
-> HDR scene color
-> Image effects such as Bloom
-> Post Exposure and color adjustments
-> Tone mapping
-> SDR or HDR display output
Emission is not Bloom
Emission represents a Lit material's self-emission; Bloom spreads bright image regions. Increasing Emission does not enable Bloom.2215
Emission does not guarantee nearby illumination; check the GI setup and method. An additional Light can illuminate an emissive sign's surroundings.22
This class-field declaration enables an HDR color picker, not camera HDR:23
[SerializeField, ColorUsage(false, true)]
private Color emissionColor = Color.white;
Post Exposure comes after HDR effects
Post Exposure in Color Adjustments runs after HDR effects, before tone mapping. Raising it is not equivalent to raising Bloom's input.20
Choose the emitter, Bloom extraction, or processed-image exposure control according to your goal.
Compare Neutral and ACES by appearance
Neutral minimizes hue/saturation changes. ACES approximates the reference ACES tone mapper, with stronger contrast and hue/saturation changes.5
For stylized emission, compare Neutral with ACES. Choose the intended look; ACES is not automatically better.
6. Enable HDR display output
URP HDR output requires Linear, an HDR-capable environment, and HDR in the active URP Asset. Check Player Other Settings:213
| Setting | Purpose |
|---|---|
| Allow HDR Display Output | Permit HDR output |
| Use HDR Display Output | Use HDR on the main display |
A monitor alone is insufficient: check OS HDR settings, GPU, driver, and Graphics API.7
Start Windows testing with a D3D12 Player. Unity 6.3 URP also lists D3D11 and Vulkan. D3D11 HDR is Player-only, not available in the Editor or exclusive fullscreen. Use borderless fullscreen.21
HDR output still maps to the display range rather than sending scene values unchanged.21
7. Inspect HDR output in code
7.1 Read output and request status
Read HDROutputSettings.main: available includes the main display and project settings; active reports current HDR output. Availability is not a monitor-hardware-only test.2425
HDRModeChangeRequested reports a pending request, not current output. This diagnostic blocks further requests while one is pending; the caller checks completion later.2627
Save HdrOutputProbe.cs and attach it to a GameObject. It uses UnityEngine only. The source revision checked Unity 6.3 API/C# declarations, not compilation or execution. HDRModeChangeRequested is a property, without ().2829
using UnityEngine;
[DisallowMultipleComponent]
public sealed class HdrOutputProbe : MonoBehaviour
{
private void Start()
{
LogStatus();
}
[ContextMenu("HDR/Log Status")]
public void LogStatus()
{
var hdr = HDROutputSettings.main;
if (hdr == null)
{
Debug.LogWarning("Could not retrieve HDR output settings.", this);
return;
}
bool available = hdr.available;
bool active = hdr.active;
Debug.Log(
$"ColorSpace={QualitySettings.activeColorSpace}, " +
$"HDR available={available}, active={active}",
this);
// Do not read request status or luminance data when HDR is unavailable.
if (!available)
{
Debug.Log("Skipped HDR details because HDR is unavailable.", this);
return;
}
Debug.Log(
$"API automaticHDRTonemapping={hdr.automaticHDRTonemapping}, " +
$"HDRModeChangeRequested={hdr.HDRModeChangeRequested}",
this);
if (!active)
{
Debug.Log("HDR output is inactive. Skipped luminance data.", this);
return;
}
// These are API values, not the effective settings of the URP Volume.
Debug.Log(
$"API paperWhiteNits={hdr.paperWhiteNits:F1} nits, " +
$"minToneMapLuminance={hdr.minToneMapLuminance} nits, " +
$"maxToneMapLuminance(10%)={hdr.maxToneMapLuminance} nits, " +
$"maxFullFrameToneMapLuminance(100%)=" +
$"{hdr.maxFullFrameToneMapLuminance} nits",
this);
}
[ContextMenu("HDR/Request On")]
public void RequestOn() => RequestMode(true);
[ContextMenu("HDR/Request Off")]
public void RequestOff() => RequestMode(false);
private void RequestMode(bool enable)
{
if (!Application.isPlaying)
{
Debug.LogWarning("Call this method while the application is playing.", this);
return;
}
var hdr = HDROutputSettings.main;
// Check availability for both enabling and disabling HDR.
if (hdr == null || !hdr.available)
{
Debug.LogWarning(
"Cannot request an HDR output mode change in this environment.",
this);
return;
}
// Do not send another request, including a reversal, while one is pending.
if (hdr.HDRModeChangeRequested)
{
Debug.LogWarning("An HDR output mode change request is still pending.", this);
return;
}
if (hdr.active == enable)
{
Debug.Log($"HDR output is already in the requested state: {enable}", this);
return;
}
hdr.RequestHDRModeChange(enable);
Debug.Log(
$"Requested HDR output change: {enable}. " +
"Call LogStatus later to check the pending state and active output.",
this);
}
}
It logs at startup. Use its context menu in Play Mode, or public methods from Player UI Buttons. Install only one HdrOutputProbe.cs, not both pasted and supplied copies.
7.2 Guard both on and off requests
RequestHDRModeChange is documented to throw when HDR is unavailable. false is not exempt. Both directions use hdr == null || !hdr.available.26
HDRModeChangeRequested and paperWhiteNits also document unavailable-environment exceptions. Read details after checking available, and luminance only when active.2730
Pending-request blocking and same-state skipping are sample policies, not mandatory Unity rules. Checking pending status first avoids treating an unfinished transition as complete.
available=true does not guarantee runtime switching everywhere. Returning from a request does not prove completion; call LogStatus() later to check pending status and active.2625
The sample lacks polling, timeouts, and disconnection recovery. Production UI needs availability rechecks, pending-state input restrictions, and completion updates. Save settings after confirming output, not logging a request.
7.3 Interpret API values correctly
API identifies HDR output settings, not photometer measurements or effective camera-Volume settings.2831
| Log field | Meaning or limitation |
|---|---|
available |
Availability for the main display and project |
active |
Current HDR state; compare against the request |
HDRModeChangeRequested |
Pending change; read only when available |
automaticHDRTonemapping |
Common API automatic tone-mapping state |
paperWhiteNits |
Reference white for automatic mapping with active HDR |
minToneMapLuminance |
Minimum input luminance retaining detail |
maxToneMapLuminance(10%) |
Maximum input luminance retaining detail: 10% bright area |
maxFullFrameToneMapLuminance(100%) |
Maximum input luminance retaining detail: entire screen bright |
maxToneMapLuminance is not an unconditional display peak. (10%) and (100%) are log labels, not API names.28
paperWhiteNits is documented for automatic HDR tone mapping with active HDR output; reading it does not prove URP uses it. automaticHDRTonemapping=false does not imply that the URP Tonemapping Volume is disabled.303231
URP Volumes can override Paper White and luminance limits. Check output status in logs and artistic settings in the camera's Volumes. The probe does not change automatic tone mapping or Paper White.315
available=true, active=false means available but inactive. available=false proves neither hardware failure nor an SDR-only monitor. These examples are not captured logs.2425
8. Paper White and highlight limits
1 nit = 1 cd/m² is a luminance unit, not a relative shader color value.28
Paper White controls reference white, including UI white—not the display's maximum brightness.21
For illustration, ordinary white might be 200 nits and highlights reach 1000 nits; UI need not reach the maximum. These are not universal recommendations. Shader 1.0 is not inherently 1 or 200 nits; conversion and settings determine that relationship.31
HDR Tonemapping adds these controls. Both Neutral and ACES support Paper White.5
| Setting | Neutral | ACES |
|---|---|---|
| Automatic white | Detect Paper White |
Detect Paper White |
| Manual white | Paper White |
Paper White |
| Brightness range |
Detect Brightness Limits, Min Nits, Max Nits
|
ACES Preset: 1000, 2000, or 4000 nits |
Disable Detect Paper White for manual white in either mode. Neutral exposes Min Nits/Max Nits when Detect Brightness Limits is off; ACES uses a preset. White controls overlap, but range controls differ.5
An ACES 1000-nit preset does not make UI white 1000 nits. Compare UI and emission, checking Inspector overrides rather than preset names.521
Display reports can be inaccurate. Consider user calibration across highlights, menus, subtitles, and loading screens.5
9. Advanced: preserve HDR data
9.1 Avoid saturating HDR color
saturate in HLSL and Shader Graph clamps to 0–1: useful for masks, destructive for HDR color before tone mapping.33
// Expressions inside a shader, not a complete Shader file.
float3 hdrColor = baseColor * intensity;
// Outputting this as scene color loses differences above 1.
float3 clippedColor = saturate(hdrColor);
Treat masks and interpolation weights separately from colors that need an HDR range.
9.2 Avoid duplicate color conversions
New Shader Graph HDR Color Nodes use Linear; old graphs may retain compatibility behavior. Unlike color textures, they may not need conversion. Check the input space before adding .linear or pow.34
9.3 Choose an appropriate RenderTexture
Intermediate RenderTexture clipping is irreversible. These formats describe raw scene-linear color before display encoding, not final HDR signals:35
| GraphicsFormat | Bits/pixel | Raw values above 1 | Alpha |
|---|---|---|---|
R8G8B8A8_UNorm |
32 | No | Yes |
B10G11R11_UFloatPack32 |
32 | Yes, positive values | No |
R16G16B16A16_SFloat |
64 | Yes | Yes |
UNorm is not always SDR: HDR10 can use PQ-encoded 10-bit UNorm. Storage format and signal encoding both matter.7
URP's 64-bit HDR Precision increases precision and bandwidth cost. HDR Alpha Processing requires 64-bit; 32-bit HDR does not necessarily include alpha.12
A target RenderTexture hides some camera HDR controls and determines target settings. Camera HDR alone does not guarantee a suitable format.13
9.4 Match the custom-pass stage
Post-processed HDR output may not mean scene-linear color. At or after AfterRenderingPostProcessing, account for gamut and luminance conversion.31
For post-processing overlays or custom UI, check white levels and duplicate conversion. A float RenderTexture cannot prevent a doubled output transform.36
9.5 EXR cannot recover discarded values
Unity can encode EXR, but the source must retain HDR data. EXR cannot restore values already lost to tone mapping or clamping.37
10. Advanced: memory and performance
HDR need not double color-buffer storage: 32-bit HDR exists. At fixed resolution, 32 to 64 bits doubles an uncompressed buffer's raw size.35
At 3840 × 2160:
32 bits/pixel:
3840 × 2160 × 4 bytes / 1024² ≈ 31.64 MiB
64 bits/pixel:
3840 × 2160 × 8 bytes / 1024² ≈ 63.28 MiB
These theoretical sizes cover one color buffer, not depth, MSAA, copies, history, or alignment. They are not measured application memory.
Compare HDR, precision, resolution, and Bloom separately, including high-quality Bloom filtering's added cost and benefit.15
On the same hardware and resolution, toggle HDR, 32/64-bit precision, and Bloom individually. Record GPU time and appearance.
11. Troubleshooting
These are starting points, not diagnoses:
| Symptom | Check first |
|---|---|
| No visible HDR difference | Above-1 values and effects that reveal them |
| Emission without glow | Post Processing, Volume Mask, Bloom override/Intensity |
| Ordinary whites glow | Emitter values and Bloom Threshold |
| HDR display receives SDR | OS/Player, Linear, Graphics API, available/active
|
| UI too bright | Paper White, composition stage, output conversion |
| HDR lost after a custom effect |
saturate, buffer formats, repeated tone mapping |
| Intermediate alpha lost | Target format, HDR Precision, Alpha Processing |
| Editor/Player mismatch | Quality pipeline asset and Graphics API constraints |
Use Window > Analysis > Render Pipeline Debugger > Lighting > HDR Debug Mode to inspect gamut and regions above Paper White, rather than relying only on the final image.38
Conclusion
Track where brightness is created, preserved, and converted for display. Compare 1, 4, and 16 with internal HDR, Bloom, and tone mapping; then inspect display output and Paper White.
Separate rendering from display-path problems, ordinary white from highlights, and always check SDR too.
-
Unity Manual, Universal RP package — Unity 6.3. ↩
-
Unity Manual, Introduction to high dynamic range (HDR). ↩
-
Unity Manual, Enable HDR Output in URP. ↩
-
Unity HDRP 17.3 documentation, HDR Output. ↩
-
Unity Manual, Tonemapping Volume Override reference for URP. ↩
-
Unity Manual, Color spaces. ↩
-
Microsoft Learn, Use DirectX with Advanced Color on high/standard dynamic range displays. See the distinctions between storage formats and encoding, and between bit depth, gamut, and dynamic range. ↩
-
Unity Manual, Set the project color space. ↩
-
Unity Manual, Differences between linear and gamma color spaces. ↩
-
Unity Manual, Disable sRGB sampling for a texture. ↩
-
Unity Scripting API, QualitySettings.renderPipeline, GraphicsSettings.currentRenderPipeline. ↩
-
Unity Manual, URP Asset reference. ↩
-
Unity Manual, Camera component reference for URP. ↩
-
Unity Manual, Add post-processing in URP. ↩
-
Unity Manual, Bloom Volume Override reference for URP. ↩
-
Unity Manual, Post-processing in URP. ↩
-
Unity Shader Graph 17.3 documentation, Property Types. ↩
-
Unity Shader Graph 17.3 documentation, Your first Shader Graph. ↩
-
Unity Manual, HDR color picker reference. ↩
-
Unity Manual, Color Adjustments Volume Override reference for URP. ↩
-
Unity Manual, HDR Output in URP. ↩
-
Unity Manual, Lit shader reference for URP. ↩
-
Unity Scripting API, ColorUsageAttribute. ↩
-
Unity Scripting API, HDROutputSettings.available. ↩
-
Unity Scripting API, HDROutputSettings.active. ↩
-
Unity Scripting API, HDROutputSettings.RequestHDRModeChange — Unity 6.0. The Japanese revision used the Unity 6.0 member page for exception conditions and request behavior, and checked the declaration against the Unity 6.3 class reference and C# reference source. It could not retrieve the 6.3 member page. Behavior in a Unity 6.3 runtime remains untested; this adaptation has not revalidated it. ↩
-
Unity Scripting API, HDROutputSettings.HDRModeChangeRequested — Unity 6.0. The Japanese revision used the Unity 6.0 member page for exception conditions and checked the property declaration against the Unity 6.3 class reference and C# reference source. This is not a Unity 6.3 runtime test. ↩
-
Unity Scripting API, HDROutputSettings. ↩
-
Unity Technologies, UnityCsReference / 6000.3 / Graphics.bindings.cs. Used in the Japanese revision to check public property and method declarations in HDROutputSettings, not native implementation details or runtime behavior. ↩
-
Unity Scripting API, HDROutputSettings.paperWhiteNits — Unity 6.3. ↩
-
Unity Manual, Troubleshoot custom render passes with HDR output in URP. ↩
-
Unity Scripting API, HDROutputSettings.automaticHDRTonemapping — Unity 6.3. ↩
-
Unity Shader Graph 17.3 documentation, Saturate Node. ↩
-
Unity Shader Graph 17.3 documentation, Color Node. ↩
-
Unity Scripting API, GraphicsFormat. ↩
-
Unity Manual, Implement a custom HDR overlay in URP. ↩
-
Unity Scripting API, ImageConversion.EncodeToEXR. ↩
-
Unity Manual, HDR Output debug views in URP. ↩
Top comments (0)