mirror of
https://github.com/mpv-player/mpv
synced 2025-01-03 05:22:23 +00:00
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:
parent
6f77444f6c
commit
9e04018f92
@ -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
|
||||
|
@ -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++)
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user