From d8a3b10f45eb10fb34ce9da3a9a76e3bd8644e3d Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Fri, 9 Jun 2017 09:16:06 +0200 Subject: vo_opengl: add new HDR tone mapping algorithm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I call it `mobius` because apparently the form f(x) = (cx+a)/(dx+b) is called a Möbius transform, which is the algorithm this is based on. In the extremes it becomes `reinhard` (param=0.0 and `clip` (param=1.0), smoothly transitioning between the two depending on the parameter. This is a useful tone mapping algorithm since the tunable mobius transform allows the user to decide the trade-off between color accuracy and detail preservation on a continuous scale. The default of 0.3 is already far more accurate than `reinhard` while also being reasonably good at preserving highlights, without suffering from the overall brightness drop and color distortion of `hable`. For these reasons, make this the new default. Also expand and improve the documentation for these tone mapping functions. --- video/out/opengl/video_shaders.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'video/out/opengl/video_shaders.c') diff --git a/video/out/opengl/video_shaders.c b/video/out/opengl/video_shaders.c index 5421589d06..95ac712f05 100644 --- a/video/out/opengl/video_shaders.c +++ b/video/out/opengl/video_shaders.c @@ -377,6 +377,21 @@ static void pass_tone_map(struct gl_shader_cache *sc, float ref_peak, GLSL(color.rgb = clamp(color.rgb, 0.0, 1.0);) break; + case TONE_MAPPING_MOBIUS: { + float j = isnan(param) ? 0.3 : param; + // solve for M(j) = j; M(ref_peak) = 1.0; M'(j) = 1.0 + // where M(x) = scale * (x+a)/(x+b) + float a = -j*j * (ref_peak - 1) / (j*j - 2*j + ref_peak), + b = (j*j - 2*j*ref_peak + ref_peak) / (ref_peak - 1); + + GLSLF("color.rgb = mix(vec3(%f) * (color.rgb + vec3(%f))\n" + " / (color.rgb + vec3(%f)),\n" + " color.rgb,\n" + " lessThanEqual(color.rgb, vec3(%f)));\n", + (b*b + 2*b*j + j*j) / (b - a), a, b, j); + break; + } + case TONE_MAPPING_REINHARD: { float contrast = isnan(param) ? 0.5 : param, offset = (1.0 - contrast) / contrast; -- cgit v1.2.3