summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiklas Haas <git@nand.wakku.to>2015-03-15 06:27:11 +0100
committerNiklas Haas <git@nand.wakku.to>2015-03-15 18:01:39 +0100
commitac1e31957d00d06071757fd271c09a045cd6f39a (patch)
treea0c29bea4f1381216aa769356b27b581697b116b
parent44a78a2be20ef3affac7e6f3aa98c0742cf019a9 (diff)
downloadmpv-ac1e31957d00d06071757fd271c09a045cd6f39a.tar.bz2
mpv-ac1e31957d00d06071757fd271c09a045cd6f39a.tar.xz
vo_opengl: add oversample scaler
This is like nearest neighbour, but the edges between pixels are linearly interpolating if needed, as if they had been (naively) oversampled.
-rw-r--r--DOCS/man/vo.rst6
-rw-r--r--video/out/gl_video.c38
2 files changed, 44 insertions, 0 deletions
diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst
index d76c95f987..b59f97b6a9 100644
--- a/DOCS/man/vo.rst
+++ b/DOCS/man/vo.rst
@@ -356,6 +356,12 @@ Available video output drivers are:
Sharpening strength. Increasing this makes the image sharper but
adds more ringing and aliasing. Defaults to 0.5.
+ ``oversample``
+ Minimum distance to an edge before interpolation is used. Setting
+ this to 0 will always interpolate edges, whereas setting it to 0.5
+ will never interpolate, thus behaving as if the regular nearest
+ neighbour algorithm was used. Defaults to 0.0.
+
``scale-radius=<r>``
Set radius for filters listed below, must be a float number between 1.0
and 16.0. Defaults to be 3.0 if not specified.
diff --git a/video/out/gl_video.c b/video/out/gl_video.c
index 5dc362335e..1b75b680c3 100644
--- a/video/out/gl_video.c
+++ b/video/out/gl_video.c
@@ -59,6 +59,7 @@ static const char *const fixed_scale_filters[] = {
"bicubic_fast",
"sharpen3",
"sharpen5",
+ "oversample",
NULL
};
@@ -1178,6 +1179,41 @@ static void pass_sample_sharpen5(struct gl_video *p, struct scaler *scaler)
GLSLF("}\n");
}
+static void pass_sample_oversample(struct gl_video *p, struct scaler *scaler,
+ int w, int h)
+{
+ GLSL(vec4 color;)
+ GLSLF("{\n");
+ GLSL(vec2 pt = 1.0 / sample_size;)
+ GLSL(vec2 pos = sample_pos + vec2(0.5) * pt;) // round to nearest
+ GLSL(vec2 fcoord = fract(pos * sample_size - vec2(0.5));)
+ // We only need to sample from the four corner pixels since we're using
+ // nearest neighbour and can compute the exact transition point
+ GLSL(vec2 baseNW = pos - fcoord * pt;)
+ GLSL(vec2 baseNE = baseNW + vec2(pt.x, 0.0);)
+ GLSL(vec2 baseSW = baseNW + vec2(0.0, pt.y);)
+ GLSL(vec2 baseSE = baseNW + pt;)
+ // Determine the mixing coefficient vector
+ gl_sc_uniform_vec2(p->sc, "output_size", (float[2]){w, h});
+ GLSL(vec2 coeff = vec2((baseSE - pos) * output_size);)
+ GLSL(coeff = clamp(coeff, 0.0, 1.0);)
+ if (scaler->params[0] > 0) { // also rules out NAN
+ GLSLF("coeff = mix(coeff, vec2(0.0), "
+ "lessThanEqual(coeff, vec2(%f)));\n", scaler->params[0]);
+ GLSLF("coeff = mix(coeff, vec2(1.0), "
+ "greaterThanEqual(coeff, vec2(%f)));\n", scaler->params[0]);
+ }
+ // Compute the right blend of colors
+ GLSL(vec4 left = mix(texture(sample_tex, baseSW),
+ texture(sample_tex, baseNW),
+ coeff.y);)
+ GLSL(vec4 right = mix(texture(sample_tex, baseSE),
+ texture(sample_tex, baseNE),
+ coeff.y);)
+ GLSL(color = mix(right, left, coeff.x);)
+ GLSLF("}\n");
+}
+
// Sample. This samples from the texture ID given by src_tex. It's hardcoded to
// use all variables and values associated with it (which includes textureN,
// texcoordN and texture_sizeN).
@@ -1212,6 +1248,8 @@ static void pass_sample(struct gl_video *p, int src_tex,
pass_sample_sharpen3(p, scaler);
} else if (strcmp(scaler->name, "sharpen5") == 0) {
pass_sample_sharpen5(p, scaler);
+ } else if (strcmp(scaler->name, "oversample") == 0) {
+ pass_sample_oversample(p, scaler, w, h);
} else if (scaler->kernel && scaler->kernel->polar) {
pass_sample_polar(p, scaler);
} else if (scaler->kernel) {