summaryrefslogtreecommitdiffstats
path: root/video/out/opengl/video_shaders.c
diff options
context:
space:
mode:
authorNiklas Haas <git@nand.wakku.to>2016-05-16 02:44:30 +0200
committerNiklas Haas <git@nand.wakku.to>2016-05-16 02:49:49 +0200
commite047cc0931a22d277d7ccd14588f905d7852f7e0 (patch)
tree6ad6d88295bf3b7ab045ce6befadd063bec84c81 /video/out/opengl/video_shaders.c
parent3cfe98c6848d888e06e5d402f9100d55ab09d755 (diff)
downloadmpv-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.c40
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.