vo_opengl: add --tone-mapping-desaturate

This helps prevent unnaturally, weirdly colorized blown out highlights
for direct images of the sunlit sky and other way-too-bright HDR
content. I was debating whether to set the default at 1.0 or 2.0, but
went with the more conservative option that preserves more detail/color.
This commit is contained in:
Niklas Haas 2017-07-06 05:43:00 +02:00
parent 6f77444f6c
commit 9e04018f92
No known key found for this signature in database
GPG Key ID: 9A09076581B27402
5 changed files with 29 additions and 6 deletions

View File

@ -4723,6 +4723,16 @@ The following video options are currently all specific to ``--vo=opengl`` and
linear
Specifies the scale factor to use while stretching. Defaults to 1.0.
``--tone-mapping-desaturate=<value>``
Apply desaturation for highlights that exceed this level of brightness. The
higher the parameter, the more color information will be preserved. This
setting helps prevent unnaturally blown-out colors for super-highlights, by
(smoothly) turning into white instead. This makes images feel more natural,
at the cost of reducing information about out-of-range colors.
The default of 2.0 is somewhat conservative and will mostly just apply to
skies or directly sunlit surfaces. A setting of 0.0 disables this option.
``--icc-profile=<file>``
Load an ICC profile and use it to transform video RGB to screen output.
Needs LittleCMS 2 support compiled in. This option overrides the

View File

@ -311,6 +311,7 @@ static const struct gl_video_opts gl_video_opts_def = {
.gamma = 1.0f,
.hdr_tone_mapping = TONE_MAPPING_MOBIUS,
.tone_mapping_param = NAN,
.tone_mapping_desat = 2.0,
.early_flush = -1,
};
@ -352,6 +353,7 @@ const struct m_sub_options gl_video_conf = {
{"gamma", TONE_MAPPING_GAMMA},
{"linear", TONE_MAPPING_LINEAR})),
OPT_FLOAT("tone-mapping-param", tone_mapping_param, 0),
OPT_FLOAT("tone-mapping-desaturate", tone_mapping_desat, 0),
OPT_FLAG("opengl-pbo", pbo, 0),
SCALER_OPTS("scale", SCALER_SCALE),
SCALER_OPTS("dscale", SCALER_DSCALE),
@ -2251,7 +2253,8 @@ static void pass_colormanage(struct gl_video *p, struct mp_colorspace src, bool
// Adapt from src to dst as necessary
pass_color_map(p->sc, src, dst, p->opts.hdr_tone_mapping,
p->opts.tone_mapping_param, p->use_linear && !osd);
p->opts.tone_mapping_param, p->opts.tone_mapping_desat,
p->use_linear && !osd);
if (p->use_lut_3d) {
gl_sc_uniform_tex(p->sc, "lut_3d", GL_TEXTURE_3D, p->lut_3d_texture);
@ -3201,6 +3204,7 @@ static void check_gl_features(struct gl_video *p)
.tex_pad_y = p->opts.tex_pad_y,
.hdr_tone_mapping = p->opts.hdr_tone_mapping,
.tone_mapping_param = p->opts.tone_mapping_param,
.tone_mapping_desat = p->opts.tone_mapping_desat,
.early_flush = p->opts.early_flush,
};
for (int n = 0; n < SCALER_COUNT; n++)

View File

@ -110,6 +110,7 @@ struct gl_video_opts {
int target_brightness;
int hdr_tone_mapping;
float tone_mapping_param;
float tone_mapping_desat;
int linear_scaling;
int correct_downscaling;
int sigmoid_upscaling;

View File

@ -522,7 +522,7 @@ void pass_inverse_ootf(struct gl_shader_cache *sc, enum mp_csp_light light, floa
// Tone map from a known peak brightness to the range [0,1]
static void pass_tone_map(struct gl_shader_cache *sc, float ref_peak,
enum tone_mapping algo, float param)
enum tone_mapping algo, float param, float desat)
{
GLSLF("// HDR tone mapping\n");
@ -530,6 +530,12 @@ static void pass_tone_map(struct gl_shader_cache *sc, float ref_peak,
GLSL(float luma = dot(src_luma, color.rgb);)
GLSL(float luma_orig = luma;)
// Desaturate the color using a coefficient dependent on the brightness
if (desat > 0 && ref_peak > desat) {
GLSLF("float overbright = max(0.0, (luma - %f) / luma);\n", desat);
GLSL(color.rgb = mix(color.rgb, vec3(luma), overbright);)
}
switch (algo) {
case TONE_MAPPING_CLIP:
GLSL(luma = clamp(luma, 0.0, 1.0);)
@ -593,7 +599,7 @@ static void pass_tone_map(struct gl_shader_cache *sc, float ref_peak,
void pass_color_map(struct gl_shader_cache *sc,
struct mp_colorspace src, struct mp_colorspace dst,
enum tone_mapping algo, float tone_mapping_param,
bool is_linear)
float tone_mapping_desat, bool is_linear)
{
GLSLF("// color mapping\n");
@ -635,8 +641,10 @@ void pass_color_map(struct gl_shader_cache *sc,
// Tone map to prevent clipping when the source signal peak exceeds the
// encodable range
if (src.sig_peak > dst_range)
pass_tone_map(sc, src.sig_peak / dst_range, algo, tone_mapping_param);
if (src.sig_peak > dst_range) {
pass_tone_map(sc, src.sig_peak / dst_range, algo, tone_mapping_param,
tone_mapping_desat);
}
// Adapt to the right colorspace if necessary
if (src.primaries != dst.primaries) {

View File

@ -44,7 +44,7 @@ void pass_inverse_ootf(struct gl_shader_cache *sc, enum mp_csp_light light, floa
void pass_color_map(struct gl_shader_cache *sc,
struct mp_colorspace src, struct mp_colorspace dst,
enum tone_mapping algo, float tone_mapping_param,
bool skip_linearization);
float tone_mapping_desat, bool is_linear);
void pass_sample_deband(struct gl_shader_cache *sc, struct deband_opts *opts,
AVLFG *lfg);