1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-23 15:22:09 +00:00

vo_opengl: implement naive anti-ringing

This is not quite the same thing as madVR's antiringing algorithm, but
it essentially does something similar.

Porting madVR's approach to elliptic coordinates will take some amount
of thought.
This commit is contained in:
Niklas Haas 2015-01-18 18:57:12 +01:00
parent 6c250505fe
commit 2d182fdea0
No known key found for this signature in database
GPG Key ID: 3BA77D4BFDB10BCE
4 changed files with 45 additions and 14 deletions

View File

@ -306,9 +306,10 @@ Available video output drivers are:
``ewa_lanczos``
Elliptic weighted average Lanczos scaling. Also known as Jinc.
Relatively slow, but very good quality. The number of taps can
be controlled with ``lradius``.
be controlled with ``lradius``. Adding extra taps makes the filter
sharper but adds more ringing.
Adding extra taps makes the filter sharper but adds more ringing.
This filter supports antiringing (see ``lantiring``).
``mitchell``
Mitchell-Netravali. The ``b`` and ``c`` parameters can be set with
@ -337,6 +338,14 @@ Available video output drivers are:
ratio, the radius that actually being used might be different
(most likely being increased a bit).
``lantiring=<value>``
Set the antiringing strength. This tries to eliminate ringing, but can
introduce other artifacts in the process. Must be a float number
between 0.0 and 1.0. The default value of 0.0 disables antiringing
entirely.
Note that this currently only affects ``ewa_lanczos``.
``scaler-resizes-only``
Disable the scaler if the video image is not resized. In that case,
``bilinear`` is used instead whatever is set with ``lscale``. Bilinear
@ -434,10 +443,10 @@ Available video output drivers are:
down by more than twice (or other factors, depending on image formats),
and ``lscale`` did not use a separable scaler.
``cparam1``, ``cparam2``, ``cradius``
``cparam1``, ``cparam2``, ``cradius``, ``cantiring``
Set filter parameters and radius for ``cscale``.
See ``lparam1``, ``lparam2`` and ``lradius``.
See ``lparam1``, ``lparam2``, ``lradius`` and ``lantiring``.
``fancy-downscaling``
When using convolution based filters, extend the filter size

View File

@ -105,6 +105,7 @@ struct scaler {
int index;
const char *name;
float params[2];
float antiring;
struct filter_kernel *kernel;
GLuint gl_lut;
const char *lut_name;
@ -367,6 +368,8 @@ const struct m_sub_options gl_video_conf = {
OPT_FLOAT("cparam2", scaler_params[1][1], 0),
OPT_FLOATRANGE("lradius", scaler_radius[0], 0, 1.0, 16.0),
OPT_FLOATRANGE("cradius", scaler_radius[1], 0, 1.0, 16.0),
OPT_FLOATRANGE("lantiring", scaler_antiring[0], 0, 0.0, 1.0),
OPT_FLOATRANGE("cantiring", scaler_antiring[1], 0, 0.0, 1.0),
OPT_FLAG("scaler-resizes-only", scaler_resizes_only, 0),
OPT_FLAG("fancy-downscaling", fancy_downscaling, 0),
OPT_FLAG("sigmoid-upscaling", sigmoid_upscaling, 0),
@ -955,9 +958,9 @@ static void shader_setup_scaler(char **shader, struct scaler *scaler, int pass)
char lut_fn[40];
if (scaler->kernel->polar) {
int radius = (int)scaler->kernel->radius;
// SAMPLE_CONVOLUTION_POLAR_R(NAME, R, LUT)
APPENDF(shader, "SAMPLE_CONVOLUTION_POLAR_R(%s, %d, %s, WEIGHTS%d)\n",
name, radius, lut_tex, unit);
// SAMPLE_CONVOLUTION_POLAR_R(NAME, R, LUT, WEIGHTS_FN, ANTIRING)
APPENDF(shader, "SAMPLE_CONVOLUTION_POLAR_R(%s, %d, %s, WEIGHTS%d, %f)\n",
name, radius, lut_tex, unit, scaler->antiring);
// Pre-compute unrolled weights matrix
APPENDF(shader, "#define WEIGHTS%d(LUT) \\\n ", unit);
@ -971,7 +974,12 @@ static void shader_setup_scaler(char **shader, struct scaler *scaler, int pass)
// Samples outside the radius are unnecessary
if (d < radius) {
APPENDF(shader, "SAMPLE_POLAR(LUT, %f, %d, %d) \\\n ",
APPENDF(shader, "SAMPLE_POLAR_%s(LUT, %f, %d, %d) \\\n ",
// The center 4 coefficients are the primary
// contributors, used to clamp the result for
// anti-ringing
(x >= 0 && y >= 0 && x <= 1 && y <= 1)
? "PRIMARY" : "HELPER",
(double)radius, x, y);
}
}
@ -1316,6 +1324,8 @@ static void init_scaler(struct gl_video *p, struct scaler *scaler)
scaler->kernel->params[n] = p->opts.scaler_params[scaler->index][n];
}
scaler->antiring = p->opts.scaler_antiring[scaler->index];
if (scaler->kernel->radius < 0) {
float radius = p->opts.scaler_radius[scaler->index];
if (!isnan(radius))

View File

@ -33,6 +33,7 @@ struct gl_video_opts {
char *dscaler;
float scaler_params[2][2];
float scaler_radius[2];
float scaler_antiring[2];
int indirect;
float gamma;
int srgb;

View File

@ -188,6 +188,7 @@ uniform float dither_quantization;
uniform float dither_center;
uniform float filter_param1_l;
uniform float filter_param1_c;
uniform float antiring_factor;
uniform vec2 dither_size;
in vec2 texcoord;
@ -298,21 +299,31 @@ float[6] weights6(sampler2D lookup, float f) {
return res; \
}
#define SAMPLE_POLAR(LUT, R, X, Y) \
#define SAMPLE_POLAR_HELPER(LUT, R, X, Y) \
w = texture1D(LUT, length(vec2(X, Y) - fcoord)/R).r; \
c = texture(tex, base + pt * vec2(X, Y)); \
wsum += w; \
res += w * texture(tex, base + pt * vec2(X, Y)); \
res += w * c; \
#define SAMPLE_CONVOLUTION_POLAR_R(NAME, R, LUT, WEIGHTS_FN) \
#define SAMPLE_POLAR_PRIMARY(LUT, R, X, Y) \
SAMPLE_POLAR_HELPER(LUT, R, X, Y) \
lo = min(lo, c); \
hi = max(hi, c); \
#define SAMPLE_CONVOLUTION_POLAR_R(NAME, R, LUT, WEIGHTS_FN, ANTIRING) \
vec4 NAME(VIDEO_SAMPLER tex, vec2 texsize, vec2 texcoord) { \
vec2 pt = vec2(1.0) / texsize; \
vec2 fcoord = fract(texcoord * texsize - vec2(0.5)); \
vec2 base = texcoord - fcoord * pt; \
vec4 res = vec4(0); \
float wsum = 0; \
vec4 res = vec4(0.0); \
vec4 lo = vec4(1.0); \
vec4 hi = vec4(0.0); \
float wsum = 0.0; \
float w; \
vec4 c; \
WEIGHTS_FN(LUT); \
return res / wsum; \
res /= wsum; \
return mix(res, clamp(res, lo, hi), ANTIRING); \
}
#ifdef DEF_SCALER0