diff options
author | Niklas Haas <git@nand.wakku.to> | 2016-05-16 02:44:30 +0200 |
---|---|---|
committer | Niklas Haas <git@nand.wakku.to> | 2016-05-16 02:49:49 +0200 |
commit | e047cc0931a22d277d7ccd14588f905d7852f7e0 (patch) | |
tree | 6ad6d88295bf3b7ab045ce6befadd063bec84c81 /video/out/opengl/video_shaders.c | |
parent | 3cfe98c6848d888e06e5d402f9100d55ab09d755 (diff) | |
download | mpv-e047cc0931a22d277d7ccd14588f905d7852f7e0.tar.bz2 mpv-e047cc0931a22d277d7ccd14588f905d7852f7e0.tar.xz |
vo_opengl: implement more HDR tonemapping algorithms
This is now a configurable option, with tunable parameters.
I got inspiration for these algorithms off wikipedia. "simple" seems to
work pretty well, but not well enough to make it a reasonable default.
Some other notable candidates:
- Local functions (e.g. based on local contrast or gradient)
- Clamp with soft knee (linear up to a point)
- Mapping in CIE L*Ch. Map L smoothly, clamp C and h.
- Color appearance models
These will have to be implemented some other time.
Note that the parameter "peak_src" to pass_tone_map should, in
principle, be auto-detected from the SEI information of the source file
where available. This will also have to be implemented in a later
commit.
Diffstat (limited to 'video/out/opengl/video_shaders.c')
-rw-r--r-- | video/out/opengl/video_shaders.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/video/out/opengl/video_shaders.c b/video/out/opengl/video_shaders.c index c63f32ca7d..237e1f39d2 100644 --- a/video/out/opengl/video_shaders.c +++ b/video/out/opengl/video_shaders.c @@ -313,6 +313,46 @@ void pass_delinearize(struct gl_shader_cache *sc, enum mp_csp_trc trc) } } +// Tone map from one brightness to another +void pass_tone_map(struct gl_shader_cache *sc, float peak_src, float peak_dst, + enum tone_mapping algo, float param) +{ + // First we renormalize to the output range + float scale = peak_src / peak_dst; + GLSLF("color.rgb *= vec3(%f);\n", scale); + + // Then we use some algorithm to map back to [0,1] + switch (algo) { + case TONE_MAPPING_CLIP: + GLSL(color.rgb = clamp(color.rgb, 0.0, 1.0);) + break; + + case TONE_MAPPING_SIMPLE: { + float contrast = isnan(param) ? 0.5 : param, + offset = (1.0 - contrast) / contrast; + GLSLF("color.rgb = color.rgb / (color.rgb + vec3(%f));\n", offset); + GLSLF("color.rgb *= vec3(%f);\n", (scale + offset) / scale); + break; + } + + case TONE_MAPPING_GAMMA: { + float gamma = isnan(param) ? 1.8 : param; + GLSLF("color.rgb = pow(color.rgb / vec3(%f), vec3(%f));\n", + scale, 1.0/gamma); + break; + } + + case TONE_MAPPING_LINEAR: { + float coeff = isnan(param) ? 1.0 : param; + GLSLF("color.rgb = vec3(%f) * color.rgb;\n", coeff / scale); + break; + } + + default: + abort(); + } +} + // Wide usage friendly PRNG, shamelessly stolen from a GLSL tricks forum post. // Obtain random numbers by calling rand(h), followed by h = permute(h) to // update the state. Assumes the texture was hooked. |