Sets an HDR tone mapper that is used to produce an SDR image at runtime when an HDR game enables auto tone mapping. The SDR image is used for GameDVR, screenshots, streaming and broadcasting.
public:
HRESULT SetHDRToneMapper(
IGraphicsUnknown* pHDRToneMapper)
pHDRToneMapper
Type: IGraphicsUnknown*
[in, optional] Pointer to a 3D texture which encodes a game’s HDR tone mapper into a 3D lookup table (LUT). If nullptr, a default tone mapper will be used during auto tone mapping. It is required that the size of the texture be 32x32x32 with format DXGI_FORMAT_R10G10B10A2_UNORM. The LUT should encode linear SDR color values, i.e. not gamma corrected.
Type: HRESULT
Returns one of the following DXGI_ERROR.
HDR games on Xbox One are required to output two swap chains, one with 10-bit HDR10 values presented to the HDR TV, and the other with an SDR image which can be used for GameDVR, screenshots, streaming and broadcasting. The SDR image can be rendered by the game, or be automatically rendered by the D3D driver when auto tone mapping is enabled by using the swap chain creation flag DXGIX_SWAP_CHAIN_FLAG_AUTOMATIC_GAMEDVR_TONEMAP. The auto tone mapper produces a good SDR image, but will most likely not have the same look as the game’s own tone mapped SDR image. This API gives a game the opportunity to provide its own tone mapper so that auto tone mapping by the D3D driver can produce an image similar to that of the game’s own SDR image. It is safe to call the API every frame, allowing a game to even generate the 3D LUT at runtime to adjust the tone mapper dynamically for different scenes.
The 3D LUT needs to convert HDR10 values to linear SDR values. The following example shader encodes a simple Reinhard tone mapper. Refer to the HDRAutoToneMapping sample for implementation details.
// The game's tone mapper. This can include operations like color grading, contrast adjustment, etc.
float3 Tonemap(float3 linearHDR)
{
// Output SDR as linear values, i.e. not gamma corrected
float3 linearSDR = linearHDR / (1.0f + linearHDR); // Reinhard tone mapper
return linearSDR;
}
// Calculate color value from UVW texture coordinates
float3 UVWToColor(float2 UV, float index, float LUTSize)
{
UV = UV - float2(0.5f / LUTSize, 0.5f / LUTSize);
return float3(UV * LUTSize / (LUTSize - 1), index / (LUTSize - 1));
}
// Calculate normalized linear value given a normalized non-linear ST.2084 value
float3 ST2084ToLinear(float3 ST2084)
{
return pow(max(pow(abs(ST2084), 1.0f / 78.84375f) - 0.8359375f, 0.0f) / (18.8515625f - 18.6875f * pow(abs(ST2084), 1.0f / 78.84375f)), 1.0f / 0.1593017578f);
}
// Color rotation matrix to rotate Rec.2020 color primaries into Rec.709
static const float3x3 from2020to709 =
{
{ 1.6604910f, -0.5876411f, -0.0728499f },
{ -0.1245505f, 1.1328999f, -0.0083494f },
{ -0.0181508f, -0.1005789f, 1.1187297f }
};
// Main shader for 3D LUT generation
float4 main(PS_IN In) : SV_Target0
{
float3 hdr10 = UVWToColor(In.TexCoord, In.LayerIndex, 32); // ST.2084 value in Rec.2020
float3 normalizedLinear = ST2084ToLinear(hdr10); // Normalized linear value in Rec.2020
float3 linearHDR = normalizedLinear * g_MaxNitsFor2084 / paperWhiteNits; // Linear HDR value in Rec.2020
float3 linearSDR = Tonemap(linearHDR); // Linear SDR value in Rec.2020
linearSDR = mul(from2020to709, linearSDR); // Linear SDR value in Rec.709
return float4(linearSDR, 1.0f);
}
Header: Declared in d3d11_x.h
Library: Use d3d11_x.lib
High Dynamic Range (HDR) output
DXGI_SWAP_CHAIN_FLAG Enumeration
White paper: HDR on Xbox One (Developer Education Materials > All NDA Whitepapers)