diff options
author | Niklas Haas <git@haasn.xyz> | 2017-10-25 17:05:52 +0200 |
---|---|---|
committer | Niklas Haas <git@haasn.xyz> | 2017-10-25 17:24:27 +0200 |
commit | c2d4fd0ef43e44c5c8caee13ae486ae05784c3a5 (patch) | |
tree | c5b7ca23177655b20cc2da382b6b175e6476ceef /video/out | |
parent | ec8cad40f243870bd7e9b030771a7052089058fa (diff) | |
download | mpv-c2d4fd0ef43e44c5c8caee13ae486ae05784c3a5.tar.bz2 mpv-c2d4fd0ef43e44c5c8caee13ae486ae05784c3a5.tar.xz |
vo_gpu: change --tone-mapping-desaturate algorithm
Comparing mpv's implementation against the ACES ODR reference samples
and algorithms, it seems like they're happy desaturating highlights
_way_ more aggressively than mpv currently does. And indeed, looking at
some example clips like The Redwoods (which is actually well-mastered),
the current desaturation produces unnatural-looking brightness fringes
where the sky meets the treeline.
Adjust the algorithm to make it apply to a much larger, more gradual
brightness region; and change the interpretation of the parameter. As a
bonus, the new parameter is actually sanely scaled (higher values = more
desaturation). Also, make it scale based on the signal level instead of
the luminance, to avoid under-desaturating bright blues.
Diffstat (limited to 'video/out')
-rw-r--r-- | video/out/gpu/video.c | 2 | ||||
-rw-r--r-- | video/out/gpu/video_shaders.c | 18 |
2 files changed, 11 insertions, 9 deletions
diff --git a/video/out/gpu/video.c b/video/out/gpu/video.c index 9191f062b6..eca74b4bb3 100644 --- a/video/out/gpu/video.c +++ b/video/out/gpu/video.c @@ -311,7 +311,7 @@ static const struct gl_video_opts gl_video_opts_def = { .gamma = 1.0f, .tone_mapping = TONE_MAPPING_MOBIUS, .tone_mapping_param = NAN, - .tone_mapping_desat = 2.0, + .tone_mapping_desat = 1.0, .early_flush = -1, }; diff --git a/video/out/gpu/video_shaders.c b/video/out/gpu/video_shaders.c index eb629a13ca..7081a10fef 100644 --- a/video/out/gpu/video_shaders.c +++ b/video/out/gpu/video_shaders.c @@ -565,18 +565,19 @@ static void pass_tone_map(struct gl_shader_cache *sc, float ref_peak, { GLSLF("// HDR tone mapping\n"); - // Desaturate the color using a coefficient dependent on the luminance - GLSL(float luma = dot(dst_luma, color.rgb);) - if (desat > 0) { - GLSLF("float overbright = max(luma - %f, 1e-6) / max(luma, 1e-6);\n", desat); - GLSL(color.rgb = mix(color.rgb, vec3(luma), overbright);) - } - // To prevent discoloration due to out-of-bounds clipping, we need to make // sure to reduce the value range as far as necessary to keep the entire // signal in range, so tone map based on the brightest component. GLSL(float sig = max(max(color.r, color.g), color.b);) - GLSL(float sig_orig = sig;) + + // Desaturate the color using a coefficient dependent on the signal + if (desat > 0) { + GLSL(float luma = dot(dst_luma, color.rgb);) + GLSL(float coeff = max(sig - 0.18, 1e-6) / max(sig, 1e-6);); + GLSLF("coeff = pow(coeff, %f);\n", 10.0 / desat); + GLSL(color.rgb = mix(color.rgb, vec3(luma), coeff);) + GLSL(sig = mix(sig, luma, coeff);) // also make sure to update `sig` + } if (!ref_peak) { // For performance, we want to do as few atomic operations on global @@ -612,6 +613,7 @@ static void pass_tone_map(struct gl_shader_cache *sc, float ref_peak, GLSLHF("const float sig_peak = %f;\n", ref_peak); } + GLSL(float sig_orig = sig;) switch (algo) { case TONE_MAPPING_CLIP: GLSLF("sig = %f * sig;\n", isnan(param) ? 1.0 : param); |