From 70f50ddc5e97020d64ea0702748a00eddebc2473 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Wed, 26 Mar 2014 01:46:38 +0100 Subject: video: Add support for non-BT.709 primaries This add support for reading primary information from lavc, categorized into BT.601-525, BT.601-625, BT.709 and BT.2020; and passes it on to the vo. In vo_opengl, we always generate the 3dlut against the wider BT.2020 and transform our source into this colorspace in the shader. --- video/out/gl_video_shaders.glsl | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) (limited to 'video/out/gl_video_shaders.glsl') diff --git a/video/out/gl_video_shaders.glsl b/video/out/gl_video_shaders.glsl index b0058f8ca6..a6ecc2eeeb 100644 --- a/video/out/gl_video_shaders.glsl +++ b/video/out/gl_video_shaders.glsl @@ -56,6 +56,13 @@ vec3 bt2020_expand(vec3 v) } #endif +// Constant matrix for conversion from BT.2020 to sRGB +const mat3 srgb_matrix = mat3( + 1.6604910, -0.1245505, -0.0181508, + -0.5876411, 1.1328999, -0.1005789, + -0.0728499, -0.0083494, 1.1187297 +); + #!section vertex_all #if __VERSION__ < 130 @@ -66,6 +73,7 @@ vec3 bt2020_expand(vec3 v) uniform mat3 transform; uniform sampler3D lut_3d; +uniform mat3 cms_matrix; // transformation from file's gamut to bt.2020 in vec2 vertex_position; in vec4 vertex_color; @@ -89,12 +97,17 @@ void main() { // NOTE: This always applies the true BT2020, maybe we need to use // approx-gamma here too? #endif +#ifdef USE_OSD_CMS_MATRIX + // Convert to the right target gamut first (to BT.709 for sRGB, + // and to BT.2020 for 3DLUT). + color.rgb = clamp(cms_matrix * color.rgb, 0, 1); +#endif #ifdef USE_OSD_3DLUT color.rgb = pow(color.rgb, vec3(1/2.4)); // linear -> 2.4 3DLUT space color = vec4(texture3D(lut_3d, color.rgb).rgb, color.a); #endif #ifdef USE_OSD_SRGB - color.rgb = srgb_compand(color.rgb); + color.rgb = srgb_compand(clamp(srgb_matrix * color.rgb, 0, 1)); #endif texcoord = vertex_texcoord; @@ -136,6 +149,7 @@ uniform sampler2D lut_l_2d; uniform sampler3D lut_3d; uniform sampler2D dither; uniform mat4x3 colormatrix; +uniform mat3 cms_matrix; uniform mat2 dither_trafo; uniform vec3 inv_gamma; uniform float input_gamma; @@ -406,16 +420,28 @@ void main() { // User-defined gamma correction factor (via the gamma sub-option) color = pow(color, inv_gamma); #endif +#ifdef USE_CMS_MATRIX + // Convert to the right target gamut first (to BT.709 for sRGB, + // and to BT.2020 for 3DLUT). + color = cms_matrix * color; +#endif #ifdef USE_3DLUT // For the 3DLUT we are arbitrarily using 2.4 as input gamma to reduce // the amount of rounding errors, so we pull up to that space first and // then pass it through the 3D texture. - color = pow(color, vec3(1/2.4)); + // + // The value is clamped to [0,1] first because the gamma function is not + // well-defined outside it. This should not be a problem because the 3dlut + // is not defined for values outside its boundaries either way, and no + // media can possibly exceed its BT.2020 source gamut either way due to + // that being the biggest taggable color space. This is just to avoid + // numerical quirks like -1e-30 turning into NaN. + color = pow(clamp(color, 0, 1), vec3(1/2.4)); color = texture3D(lut_3d, color).rgb; #endif #ifdef USE_SRGB - // Compand from the linear scaling gamma to the sRGB output gamma - color = srgb_compand(color.rgb); + // Adapt and compand from the linear BT2020 source to the sRGB output + color = srgb_compand(clamp(srgb_matrix * color, 0, 1)); #endif #ifdef USE_DITHER vec2 dither_pos = gl_FragCoord.xy / dither_size; -- cgit v1.2.3