summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.xyz>2017-07-06 05:43:00 +0200
committerNiklas Haas <git@haasn.xyz>2017-07-06 05:43:00 +0200
commit9e04018f920c6c8eed46a779af00f9543e6539d6 (patch)
treed88e2b05dfb2f6f2a9d902d69357ef976ab99017
parent6f77444f6c2d82feeebcd46a2b2f7ae3252648ef (diff)
downloadmpv-9e04018f920c6c8eed46a779af00f9543e6539d6.tar.bz2
mpv-9e04018f920c6c8eed46a779af00f9543e6539d6.tar.xz
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.
-rw-r--r--DOCS/man/options.rst10
-rw-r--r--video/out/opengl/video.c6
-rw-r--r--video/out/opengl/video.h1
-rw-r--r--video/out/opengl/video_shaders.c16
-rw-r--r--video/out/opengl/video_shaders.h2
5 files changed, 29 insertions, 6 deletions
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 896a6f3dad..7e6199b5e3 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -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
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c
index bc218792fd..f2f5260c74 100644
--- a/video/out/opengl/video.c
+++ b/video/out/opengl/video.c
@@ -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++)
diff --git a/video/out/opengl/video.h b/video/out/opengl/video.h
index 4a51d421ad..b4f91b802f 100644
--- a/video/out/opengl/video.h
+++ b/video/out/opengl/video.h
@@ -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;
diff --git a/video/out/opengl/video_shaders.c b/video/out/opengl/video_shaders.c
index cbd566ff0c..995fbd2a1a 100644
--- a/video/out/opengl/video_shaders.c
+++ b/video/out/opengl/video_shaders.c
@@ -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) {
diff --git a/video/out/opengl/video_shaders.h b/video/out/opengl/video_shaders.h
index 6498033ad1..b0b8b4214e 100644
--- a/video/out/opengl/video_shaders.h
+++ b/video/out/opengl/video_shaders.h
@@ -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);