diff options
author | CrystalP <crystalp@kodi.tv> | 2023-06-05 00:07:16 -0400 |
---|---|---|
committer | CrystalP <crystalp@kodi.tv> | 2023-06-11 15:53:56 -0400 |
commit | 582132de25879ecd11907781e6a7f664afbdd4e2 (patch) | |
tree | b3f51b67f39cda9a2c7bff92ae2cc489db634702 /system/shaders | |
parent | 5b79de77edb2a39e0176fd941d5485518c1c6595 (diff) |
[Windows] Fix HLG to PQ shader conversion to match BT.2100 formulas
* HLG OOTF and inverse OETF, inverse PQ)
* Add formula for Lw <> 1000 nits
Diffstat (limited to 'system/shaders')
-rw-r--r-- | system/shaders/output_d3d.fx | 35 |
1 files changed, 26 insertions, 9 deletions
diff --git a/system/shaders/output_d3d.fx b/system/shaders/output_d3d.fx index eebc200a19..fd5fff1d53 100644 --- a/system/shaders/output_d3d.fx +++ b/system/shaders/output_d3d.fx @@ -96,19 +96,25 @@ float3 inversePQ(float3 x) } #endif #if defined(KODI_HLG_TO_PQ) + +// HLG inverse OETF - BT.2100 +// input: non-linear signal [0,1] range +// output: linear [0,1] range float3 inverseHLG(float3 x) { - const float B67_a = 0.17883277f; - const float B67_b = 0.28466892f; - const float B67_c = 0.55991073f; - const float B67_inv_r2 = 4.0f; - x = (x <= 0.5f) ? x * x * B67_inv_r2 : exp((x - B67_c) / B67_a) + B67_b; + static const float B67_a = 0.17883277f; + static const float B67_b = 0.28466892f; // b = 1 - 4*a + static const float B67_c = 0.55991073f; // c = 0.5 - a*log(4*a) + x = (x <= 0.5f) ? x * x / 3.0f : (exp((x - B67_c) / B67_a) + B67_b) / 12.0f; return x; } +// PQ inverse EOTF, BT.2100 +// input: linear cd/m2 [0,10000] range +// output: non-linear [0,1] range float3 tranferPQ(float3 x) { - x = pow(x / 1000.0f, ST2084_m1); + x = pow(x / 10000.0f, ST2084_m1); x = (ST2084_c1 + ST2084_c2 * x) / (1.0f + ST2084_c3 * x); x = pow(x, ST2084_m2); return x; @@ -136,10 +142,21 @@ float4 output4(float4 color, float2 uv) color.rgb = pow(color.rgb, 1.0f / 2.2f); #endif #if defined(KODI_HLG_TO_PQ) + + // Reference: BT.2100, Table 5, HLG Reference EOTF + + // Display peak luminance in cd/m2 + static const float HLG_Lw = 1000.0f; + static const float HLG_gamma = 1.2f + 0.42f * log10(HLG_Lw / 1000.0f); + + // color.rgb: E', range [0,1] color.rgb = inverseHLG(color.rgb); - float3 ootf_2020 = float3(0.2627f, 0.6780f, 0.0593f); - float ootf_ys = 2000.0f * dot(ootf_2020, color.rgb); - color.rgb *= pow(ootf_ys, 0.2f); + // color.rgb: E, range [0,1] + static const float3 bt2020_lum_rgbweights = float3(0.2627f, 0.6780f, 0.0593f); + float HLG_Ys = dot(bt2020_lum_rgbweights, color.rgb); + color.rgb *= HLG_Lw * pow(HLG_Ys, HLG_gamma - 1.0f); + + // color.rgb: FD, in cd/m2 color.rgb = tranferPQ(color.rgb); #endif #if defined(KODI_3DLUT) |