summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/vo.rst16
-rw-r--r--video/out/opengl/nnedi3.c33
-rw-r--r--video/out/opengl/nnedi3.h6
-rw-r--r--video/out/opengl/superxbr.c29
-rw-r--r--video/out/opengl/superxbr.h2
-rw-r--r--video/out/opengl/video.c129
-rw-r--r--video/out/opengl/video_shaders.c57
-rw-r--r--video/out/opengl/video_shaders.h3
8 files changed, 138 insertions, 137 deletions
diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst
index 4d6972e5a3..7892761581 100644
--- a/DOCS/man/vo.rst
+++ b/DOCS/man/vo.rst
@@ -763,14 +763,26 @@ Available video output drivers are:
definitions to that shader pass, where NAME is the name of the bound
texture:
- sampler NAME
- The bound texture itself.
+ vec4 NAME_tex(vec2 pos)
+ The sampling function to use to access the texture at a certain
+ spot (in texture coordinate space, range [0,1]). This takes care
+ of any necessary normalization conversions.
+ vec4 NAME_texOff(vec2 offset)
+ Sample the texture at a certain offset in pixels. This works like
+ NAME_tex but additionally takes care of necessary rotations, so
+ that sampling at e.g. vec2(-1,0) is always one pixel to the left.
vec2 NAME_pos
The local texture coordinate of that texture, range [0,1].
vec2 NAME_size
The (rotated) size in pixels of the texture.
+ mat2 NAME_rot
+ The rotation matrix associated with this texture. (Rotates
+ pixel space to texture coordinates)
vec2 NAME_pt
The (unrotated) size of a single pixel, range [0,1].
+ sampler NAME_raw
+ The raw bound texture itself. The use of this should be
+ avoided unless absolutely necessary.
In addition, the global uniforms described in ``post-shaders`` are
also available.
diff --git a/video/out/opengl/nnedi3.c b/video/out/opengl/nnedi3.c
index 3c12fcc623..74eb083786 100644
--- a/video/out/opengl/nnedi3.c
+++ b/video/out/opengl/nnedi3.c
@@ -96,9 +96,9 @@ const float* get_nnedi3_weights(const struct nnedi3_opts *conf, int *size)
return (const float*)(nnedi3_weights + offset * 4);
}
-void pass_nnedi3(GL *gl, struct gl_shader_cache *sc, int planes, int tex_num,
- int step, float tex_mul, const struct nnedi3_opts *conf,
- struct gl_transform *transform, GLenum tex_target)
+void pass_nnedi3(GL *gl, struct gl_shader_cache *sc, int step,
+ const struct nnedi3_opts *conf,
+ struct gl_transform *transform)
{
assert(0 <= step && step < 2);
@@ -131,23 +131,23 @@ void pass_nnedi3(GL *gl, struct gl_shader_cache *sc, int planes, int tex_num,
GLSLH(#pragma optionNV(fastprecision on))
}
- GLSLHF("float nnedi3(%s tex, vec2 pos, vec2 tex_size, vec2 pixel_size, int plane, float tex_mul) {\n", mp_sampler_type(tex_target));
+ GLSLHF("float nnedi3() {\n");
if (step == 0) {
*transform = (struct gl_transform){{{1.0,0.0}, {0.0,2.0}}, {0.0,-0.5}};
- GLSLH(if (fract(pos.y * tex_size.y) < 0.5)
- return texture(tex, pos + vec2(0, 0.25) * pixel_size)[plane] * tex_mul;)
+ GLSLH(if ((transpose(HOOKED_rot) * fract(HOOKED_pos * HOOKED_size)).y < 0.5)
+ return HOOKED_texOff(vec2(0, 0.25)).x;)
GLSLHF("#define GET(i, j) "
- "(texture(tex, pos+vec2((i)-(%f),(j)-(%f)+0.25) * pixel_size)[plane]*tex_mul)\n",
+ "HOOKED_texOff(vec2((i)-(%f),(j)-(%f)+0.25)).x\n",
width / 2.0 - 1, (height - 1) / 2.0);
} else {
*transform = (struct gl_transform){{{2.0,0.0}, {0.0,1.0}}, {-0.5,0.0}};
- GLSLH(if (fract(pos.x * tex_size.x) < 0.5)
- return texture(tex, pos + vec2(0.25, 0) * pixel_size)[plane] * tex_mul;)
+ GLSLH(if (fract(HOOKED_pos.x * HOOKED_size.x) < 0.5)
+ return HOOKED_texOff(vec2(0.25, 0)).x;)
GLSLHF("#define GET(i, j) "
- "(texture(tex, pos+vec2((j)-(%f)+0.25,(i)-(%f)) * pixel_size)[plane]*tex_mul)\n",
+ "HOOKED_texOff(vec2((j)-(%f)+0.25,(i)-(%f))).x\n",
(height - 1) / 2.0, width / 2.0 - 1);
}
@@ -226,12 +226,7 @@ void pass_nnedi3(GL *gl, struct gl_shader_cache *sc, int planes, int tex_num,
GLSLHF("}\n"); // nnedi3
- GLSL(color = vec4(1.0);)
-
- for (int i = 0; i < planes; i++) {
- GLSLF("color[%d] = nnedi3(texture%d, texcoord%d, texture_size%d, pixel_size%d, %d, %f);\n",
- i, tex_num, tex_num, tex_num, tex_num, i, tex_mul);
- }
+ GLSL(color.x = nnedi3();)
}
#else
@@ -244,9 +239,9 @@ const float* get_nnedi3_weights(const struct nnedi3_opts *conf, int *size)
return NULL;
}
-void pass_nnedi3(GL *gl, struct gl_shader_cache *sc, int planes, int tex_num,
- int step, float tex_mul, const struct nnedi3_opts *conf,
- struct gl_transform *transform, GLenum tex_target)
+void pass_nnedi3(GL *gl, struct gl_shader_cache *sc, int step,
+ const struct nnedi3_opts *conf,
+ struct gl_transform *transform)
{
}
diff --git a/video/out/opengl/nnedi3.h b/video/out/opengl/nnedi3.h
index c3895a0773..8cd1a65815 100644
--- a/video/out/opengl/nnedi3.h
+++ b/video/out/opengl/nnedi3.h
@@ -38,8 +38,8 @@ extern const struct m_sub_options nnedi3_conf;
const float* get_nnedi3_weights(const struct nnedi3_opts *conf, int *size);
-void pass_nnedi3(GL *gl, struct gl_shader_cache *sc, int planes, int tex_num,
- int step, float tex_mul, const struct nnedi3_opts *conf,
- struct gl_transform *transform, GLenum tex_target);
+void pass_nnedi3(GL *gl, struct gl_shader_cache *sc, int step,
+ const struct nnedi3_opts *conf,
+ struct gl_transform *transform);
#endif
diff --git a/video/out/opengl/superxbr.c b/video/out/opengl/superxbr.c
index 323ed18513..b7b9a53afd 100644
--- a/video/out/opengl/superxbr.c
+++ b/video/out/opengl/superxbr.c
@@ -174,7 +174,7 @@ static void superxbr_step_h(struct gl_shader_cache *sc,
}
// Pick the two best directions and mix them together
- GLSLHF("float str = smoothstep(0.0, %f + 1e-6, abs(tex_mul*d_edge));\n",
+ GLSLHF("float str = smoothstep(0.0, %f + 1e-6, abs(d_edge));\n",
conf->edge_strength);
GLSLH(res = mix(mix(d2c, d1c, step(0.0, d_edge)), \
mix(hc, vc, step(0.0, o_edge)), 1.0 - str);)
@@ -187,7 +187,7 @@ static void superxbr_step_h(struct gl_shader_cache *sc,
GLSLHF("} // step\n");
}
-void pass_superxbr(struct gl_shader_cache *sc, int id, int step, float tex_mul,
+void pass_superxbr(struct gl_shader_cache *sc, int step,
const struct superxbr_opts *conf,
struct gl_transform *transform)
{
@@ -196,49 +196,48 @@ void pass_superxbr(struct gl_shader_cache *sc, int id, int step, float tex_mul,
assert(0 <= step && step < 2);
GLSLF("// superxbr (step %d)\n", step);
- GLSLHF("#define tex texture%d\n", id);
- GLSLHF("#define tex_size texture_size%d\n", id);
- GLSLHF("#define tex_mul %f\n", tex_mul);
- GLSLHF("#define pt pixel_size%d\n", id);
// We use a sub-function in the header so we can return early
- GLSLHF("float superxbr(vec2 pos) {\n");
+ GLSLHF("float superxbr() {\n");
GLSLH(float i[4*4];)
GLSLH(float res;)
GLSLH(#define i(x,y) i[(x)*4+(y)])
if (step == 0) {
*transform = (struct gl_transform){{{2.0,0.0}, {0.0,2.0}}, {-0.5,-0.5}};
- GLSLH(vec2 dir = fract(pos * tex_size) - 0.5;)
+ GLSLH(vec2 dir = fract(HOOKED_pos * HOOKED_size) - 0.5;)
+ GLSLH(dir = transpose(HOOKED_rot) * dir;)
// Optimization: Discard (skip drawing) unused pixels, except those
// at the edge.
- GLSLH(vec2 dist = tex_size * min(pos, vec2(1.0) - pos);)
+ GLSLH(vec2 dist = HOOKED_size * min(HOOKED_pos, vec2(1.0) - HOOKED_pos);)
GLSLH(if (dir.x * dir.y < 0.0 && dist.x > 1.0 && dist.y > 1.0)
return 0.0;)
GLSLH(if (dir.x < 0.0 || dir.y < 0.0 || dist.x < 1.0 || dist.y < 1.0)
- return texture(tex, pos - pt * dir).x;)
+ return HOOKED_texOff(-dir).x;)
// Load the input samples
GLSLH(for (int x = 0; x < 4; x++))
GLSLH(for (int y = 0; y < 4; y++))
- GLSLH(i(x,y) = texture(tex, pos + pt * vec2(x-1.25, y-1.25)).x;)
+ GLSLH(i(x,y) = HOOKED_texOff(vec2(x-1.25, y-1.25)).x;)
} else {
*transform = (struct gl_transform){{{1.0,0.0}, {0.0,1.0}}, {0.0,0.0}};
- GLSLH(vec2 dir = fract(pos * tex_size / 2.0) - 0.5;)
+ // This is the second pass, so it will never be rotated
+ GLSLH(vec2 dir = fract(HOOKED_pos * HOOKED_size / 2.0) - 0.5;)
+
GLSLH(if (dir.x * dir.y > 0.0)
- return texture(tex, pos).x;)
+ return HOOKED_texOff(0).x;)
GLSLH(for (int x = 0; x < 4; x++))
GLSLH(for (int y = 0; y < 4; y++))
- GLSLH(i(x,y) = texture(tex, pos + pt * vec2(x+y-3, y-x)).x;)
+ GLSLH(i(x,y) = HOOKED_texOff(vec2(x+y-3, y-x)).x;)
}
superxbr_step_h(sc, conf, &params[step]);
GLSLH(return res;)
GLSLHF("}\n");
- GLSLF("color.x = tex_mul * superxbr(texcoord%d);\n", id);
+ GLSL(color.x = superxbr();)
}
diff --git a/video/out/opengl/superxbr.h b/video/out/opengl/superxbr.h
index 7aa46eff7c..f9888d37e4 100644
--- a/video/out/opengl/superxbr.h
+++ b/video/out/opengl/superxbr.h
@@ -24,7 +24,7 @@
extern const struct superxbr_opts superxbr_opts_def;
extern const struct m_sub_options superxbr_conf;
-void pass_superxbr(struct gl_shader_cache *sc, int id, int step, float tex_mul,
+void pass_superxbr(struct gl_shader_cache *sc, int step,
const struct superxbr_opts *conf,
struct gl_transform *transform);
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c
index ae1800821f..085bc825af 100644
--- a/video/out/opengl/video.c
+++ b/video/out/opengl/video.c
@@ -217,7 +217,6 @@ struct gl_video {
struct fbotex blend_subs_fbo;
struct fbotex output_fbo;
struct fbosurface surfaces[FBOSURFACES_MAX];
- struct fbotex prescale_fbo[MAX_PRESCALE_PASSES];
int surface_idx;
int surface_now;
@@ -602,9 +601,6 @@ static void uninit_rendering(struct gl_video *p)
fbotex_uninit(&p->indirect_fbo);
fbotex_uninit(&p->blend_subs_fbo);
- for (int pass = 0; pass < MAX_PRESCALE_PASSES; pass++)
- fbotex_uninit(&p->prescale_fbo[pass]);
-
for (int n = 0; n < FBOSURFACES_MAX; n++)
fbotex_uninit(&p->surfaces[n].fbotex);
@@ -910,9 +906,11 @@ static void pass_prepare_src_tex(struct gl_video *p)
char texture_name[32];
char texture_size[32];
+ char texture_rot[32];
char pixel_size[32];
snprintf(texture_name, sizeof(texture_name), "texture%d", n);
snprintf(texture_size, sizeof(texture_size), "texture_size%d", n);
+ snprintf(texture_rot, sizeof(texture_rot), "texture_rot%d", n);
snprintf(pixel_size, sizeof(pixel_size), "pixel_size%d", n);
if (s->use_integer) {
@@ -926,6 +924,7 @@ static void pass_prepare_src_tex(struct gl_video *p)
f[1] = s->tex_h;
}
gl_sc_uniform_vec2(sc, texture_size, f);
+ gl_sc_uniform_mat2(sc, texture_rot, true, (float *)s->transform.m);
gl_sc_uniform_vec2(sc, pixel_size, (GLfloat[]){1.0f / f[0],
1.0f / f[1]});
@@ -1045,12 +1044,29 @@ static void uninit_scaler(struct gl_video *p, struct scaler *scaler)
scaler->initialized = false;
}
-static void hook_prelude(struct gl_video *p, const char *name, int id)
+static void hook_prelude(struct gl_video *p, const char *name, int id,
+ struct img_tex tex)
{
- GLSLHF("#define %s texture%d\n", name, id);
+ GLSLHF("#define %s_raw texture%d\n", name, id);
GLSLHF("#define %s_pos texcoord%d\n", name, id);
GLSLHF("#define %s_size texture_size%d\n", name, id);
+ GLSLHF("#define %s_rot texture_rot%d\n", name, id);
GLSLHF("#define %s_pt pixel_size%d\n", name, id);
+
+ // Set up the sampling functions
+ GLSLHF("#define %s_tex(pos) (%f * vec4(texture(%s_raw, pos)).%s)\n",
+ name, tex.multiplier, name, tex.swizzle[0] ? tex.swizzle : "rgba");
+
+ // Since the extra matrix multiplication impacts performance,
+ // skip it unless the texture was actually rotated
+ if (gl_transform_eq(tex.transform, identity_trans)) {
+ GLSLHF("#define %s_texOff(off) %s_tex(%s_pos + %s_pt * vec2(off))\n",
+ name, name, name, name);
+ } else {
+ GLSLHF("#define %s_texOff(off) "
+ "%s_tex(%s_pos + %s_rot * vec2(off)/%s_size)\n",
+ name, name, name, name, name);
+ }
}
static bool saved_tex_find(struct gl_video *p, const char *name,
@@ -1116,8 +1132,8 @@ static struct img_tex pass_hook(struct gl_video *p, const char *name,
// This is a special name that means "currently hooked texture"
if (strcmp(bind_name, "HOOKED") == 0) {
int id = pass_bind(p, tex);
- hook_prelude(p, "HOOKED", id);
- hook_prelude(p, name, id);
+ hook_prelude(p, "HOOKED", id, tex);
+ hook_prelude(p, name, id, tex);
continue;
}
@@ -1130,7 +1146,7 @@ static struct img_tex pass_hook(struct gl_video *p, const char *name,
return tex;
}
- hook_prelude(p, bind_name, pass_bind(p, bind_tex));
+ hook_prelude(p, bind_name, pass_bind(p, bind_tex), bind_tex);
}
// Run the actual hook. This generates a series of GLSL shader
@@ -1502,33 +1518,6 @@ static void upload_nnedi3_weights(struct gl_video *p)
}
}
-// Applies a single pass of the prescaler, and accumulates the offset in
-// pass_transform.
-static void pass_prescale_luma_step(struct gl_video *p, struct img_tex tex,
- struct gl_transform *step_transform,
- int step)
-{
- int id = pass_bind(p, tex);
- int planes = tex.components;
-
- switch(p->opts.prescale_luma) {
- case 1:
- assert(planes == 1);
- pass_superxbr(p->sc, id, step, tex.multiplier,
- p->opts.superxbr_opts, step_transform);
- break;
- case 2:
- upload_nnedi3_weights(p);
- pass_nnedi3(p->gl, p->sc, planes, id, step, tex.multiplier,
- p->opts.nnedi3_opts, step_transform, tex.gl_target);
- break;
- default:
- abort();
- }
-
- skip_unused(p, planes);
-}
-
// Returns true if two img_texs are semantically equivalent (same metadata)
static bool img_tex_equiv(struct img_tex a, struct img_tex b)
{
@@ -1569,33 +1558,22 @@ static void pass_add_hooks(struct gl_video *p, struct tex_hook hook,
static void deband_hook(struct gl_video *p, struct img_tex tex,
struct gl_transform *trans, void *priv)
{
- // We could use the hook binding mechanism here but the existing code
- // already assumes we just know an ID so just do this for simplicity
- int id = pass_bind(p, tex);
- pass_sample_deband(p->sc, p->opts.deband_opts, id, tex.multiplier,
- tex.gl_target, &p->lfg);
- skip_unused(p, tex.components);
+ pass_sample_deband(p->sc, p->opts.deband_opts, &p->lfg);
}
-static void prescale_hook(struct gl_video *p, struct img_tex tex,
+static void superxbr_hook(struct gl_video *p, struct img_tex tex,
struct gl_transform *trans, void *priv)
{
- struct gl_transform step_trans = identity_trans;
- pass_prescale_luma_step(p, tex, &step_trans, 0);
- gl_transform_trans(step_trans, trans);
-
- // We render out an FBO *inside* this hook, which is normally quite
- // unusual but here it allows us to work around the lack of real closures.
- // Unfortunately it means we need to duplicate some work to compute the
- // new FBO size
- struct fbotex *fbo = priv;
- int w = tex.w * (int)step_trans.m[0][0],
- h = tex.h * (int)step_trans.m[1][1];
- finish_pass_fbo(p, fbo, w, h, 0);
- tex = img_tex_fbo(fbo, tex.type, tex.components);
+ int step = (uintptr_t)priv;
+ pass_superxbr(p->sc, step, p->opts.superxbr_opts, trans);
+}
- pass_prescale_luma_step(p, tex, &step_trans, 1);
- gl_transform_trans(step_trans, trans);
+static void nnedi3_hook(struct gl_video *p, struct img_tex tex,
+ struct gl_transform *trans, void *priv)
+{
+ int step = (uintptr_t)priv;
+ upload_nnedi3_weights(p);
+ pass_nnedi3(p->gl, p->sc, step, p->opts.nnedi3_opts, trans);
}
static void unsharp_hook(struct gl_video *p, struct img_tex tex,
@@ -1617,7 +1595,7 @@ static void user_hook_old(struct gl_video *p, struct img_tex tex,
load_shader(p, bstr0(body));
const char *fn_name = get_custom_shader_fn(p, body);
GLSLF("// custom shader\n");
- GLSLF("color = %s(HOOKED, HOOKED_pos, HOOKED_size);\n", fn_name);
+ GLSLF("color = %s(HOOKED_raw, HOOKED_pos, HOOKED_size);\n", fn_name);
}
// Returns 1.0 on failure to at least create a legal FBO
@@ -1784,17 +1762,36 @@ static void pass_hook_user_shaders(struct gl_video *p, char **shaders)
static void gl_video_setup_hooks(struct gl_video *p)
{
if (p->opts.deband) {
- pass_add_hooks(p, (struct tex_hook) {.hook = deband_hook},
+ pass_add_hooks(p, (struct tex_hook) {.hook = deband_hook,
+ .bind_tex = {"HOOKED"}},
HOOKS("LUMA", "CHROMA", "RGB", "XYZ"));
}
int prescale_passes = get_prescale_passes(p);
- for (int i = 0; i < prescale_passes; i++) {
- pass_add_hook(p, (struct tex_hook) {
- .hook_tex = "LUMA",
- .hook = prescale_hook,
- .priv = &p->prescale_fbo[i],
- });
+ if (p->opts.prescale_luma == 1) { // superxbr
+ for (int i = 0; i < prescale_passes; i++) {
+ for (int step = 0; step < 2; step++) {
+ pass_add_hook(p, (struct tex_hook) {
+ .hook_tex = "LUMA",
+ .bind_tex = {"HOOKED"},
+ .hook = superxbr_hook,
+ .priv = (void *)(uintptr_t)step,
+ });
+ }
+ }
+ }
+
+ if (p->opts.prescale_luma == 2) { // nnedi3
+ for (int i = 0; i < prescale_passes; i++) {
+ for (int step = 0; step < 2; step++) {
+ pass_add_hook(p, (struct tex_hook) {
+ .hook_tex = "LUMA",
+ .bind_tex = {"HOOKED"},
+ .hook = nnedi3_hook,
+ .priv = (void *)(uintptr_t)step,
+ });
+ }
+ }
}
if (p->opts.unsharp != 0.0) {
diff --git a/video/out/opengl/video_shaders.c b/video/out/opengl/video_shaders.c
index 8d3b1e0e40..8956ec37b9 100644
--- a/video/out/opengl/video_shaders.c
+++ b/video/out/opengl/video_shaders.c
@@ -290,7 +290,7 @@ void pass_delinearize(struct gl_shader_cache *sc, enum mp_csp_trc trc)
// 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.
+// update the state. Assumes the texture was hooked.
static void prng_init(struct gl_shader_cache *sc, AVLFG *lfg)
{
GLSLH(float mod289(float x) { return x - floor(x / 289.0) * 289.0; })
@@ -298,7 +298,7 @@ static void prng_init(struct gl_shader_cache *sc, AVLFG *lfg)
GLSLH(float rand(float x) { return fract(x / 41.0); })
// Initialize the PRNG by hashing the position + a random uniform
- GLSL(vec3 _m = vec3(pos, random) + vec3(1.0);)
+ GLSL(vec3 _m = vec3(HOOKED_pos, random) + vec3(1.0);)
GLSL(float h = permute(permute(permute(_m.x)+_m.y)+_m.z);)
gl_sc_uniform_f(sc, "random", (double)av_lfg_get(lfg) / UINT32_MAX);
}
@@ -331,44 +331,40 @@ const struct m_sub_options deband_conf = {
.defaults = &deband_opts_def,
};
-// Stochastically sample a debanded result from a given texture
+// Stochastically sample a debanded result from a hooked texture.
void pass_sample_deband(struct gl_shader_cache *sc, struct deband_opts *opts,
- int tex_num, float tex_mul, GLenum tex_target, AVLFG *lfg)
+ AVLFG *lfg)
{
- // Set up common variables and initialize the PRNG
+ // Initialize the PRNG
GLSLF("{\n");
- sampler_prelude(sc, tex_num);
prng_init(sc, lfg);
// Helper: Compute a stochastic approximation of the avg color around a
// pixel
- GLSLHF("vec4 average(%s tex, vec2 pos, vec2 pt, float range, inout float h) {",
- mp_sampler_type(tex_target));
+ GLSLHF("vec4 average(float range, inout float h) {\n");
// Compute a random rangle and distance
GLSLH(float dist = rand(h) * range; h = permute(h);)
GLSLH(float dir = rand(h) * 6.2831853; h = permute(h);)
-
- GLSLHF("pt *= dist;\n");
- GLSLH(vec2 o = vec2(cos(dir), sin(dir));)
+ GLSLH(vec2 o = dist * vec2(cos(dir), sin(dir));)
// Sample at quarter-turn intervals around the source pixel
GLSLH(vec4 ref[4];)
- GLSLH(ref[0] = texture(tex, pos + pt * vec2( o.x, o.y));)
- GLSLH(ref[1] = texture(tex, pos + pt * vec2(-o.y, o.x));)
- GLSLH(ref[2] = texture(tex, pos + pt * vec2(-o.x, -o.y));)
- GLSLH(ref[3] = texture(tex, pos + pt * vec2( o.y, -o.x));)
+ GLSLH(ref[0] = HOOKED_texOff(vec2( o.x, o.y));)
+ GLSLH(ref[1] = HOOKED_texOff(vec2(-o.y, o.x));)
+ GLSLH(ref[2] = HOOKED_texOff(vec2(-o.x, -o.y));)
+ GLSLH(ref[3] = HOOKED_texOff(vec2( o.y, -o.x));)
// Return the (normalized) average
- GLSLHF("return %f * (ref[0] + ref[1] + ref[2] + ref[3])/4.0;\n", tex_mul);
- GLSLH(})
+ GLSLH(return (ref[0] + ref[1] + ref[2] + ref[3])/4.0;)
+ GLSLHF("}\n");
// Sample the source pixel
- GLSLF("color = %f * texture(tex, pos);\n", tex_mul);
+ GLSL(color = HOOKED_tex(HOOKED_pos);)
GLSLF("vec4 avg, diff;\n");
for (int i = 1; i <= opts->iterations; i++) {
// Sample the average pixel and use it instead of the original if
// the difference is below the given threshold
- GLSLF("avg = average(tex, pos, pt, %f, h);\n", i * opts->range);
+ GLSLF("avg = average(%f, h);\n", i * opts->range);
GLSL(diff = abs(color - avg);)
GLSLF("color = mix(avg, color, greaterThan(diff, vec4(%f)));\n",
opts->threshold / (i * 16384.0));
@@ -383,20 +379,21 @@ void pass_sample_deband(struct gl_shader_cache *sc, struct deband_opts *opts,
GLSLF("}\n");
}
+// Assumes the texture was hooked
void pass_sample_unsharp(struct gl_shader_cache *sc, float param) {
GLSLF("// unsharp\n");
GLSLF("{\n");
- GLSL(vec2 st1 = pt * 1.2;)
- GLSL(vec4 p = texture(tex, pos);)
- GLSL(vec4 sum1 = texture(tex, pos + st1 * vec2(+1, +1))
- + texture(tex, pos + st1 * vec2(+1, -1))
- + texture(tex, pos + st1 * vec2(-1, +1))
- + texture(tex, pos + st1 * vec2(-1, -1));)
- GLSL(vec2 st2 = pt * 1.5;)
- GLSL(vec4 sum2 = texture(tex, pos + st2 * vec2(+1, 0))
- + texture(tex, pos + st2 * vec2( 0, +1))
- + texture(tex, pos + st2 * vec2(-1, 0))
- + texture(tex, pos + st2 * vec2( 0, -1));)
+ GLSL(float st1 = 1.2;)
+ GLSL(vec4 p = HOOKED_tex(HOOKED_pos);)
+ GLSL(vec4 sum1 = HOOKED_texOff(st1 * vec2(+1, +1))
+ + HOOKED_texOff(st1 * vec2(+1, -1))
+ + HOOKED_texOff(st1 * vec2(-1, +1))
+ + HOOKED_texOff(st1 * vec2(-1, -1));)
+ GLSL(float st2 = 1.5;)
+ GLSL(vec4 sum2 = HOOKED_texOff(st2 * vec2(+1, 0))
+ + HOOKED_texOff(st2 * vec2( 0, +1))
+ + HOOKED_texOff(st2 * vec2(-1, 0))
+ + HOOKED_texOff(st2 * vec2( 0, -1));)
GLSL(vec4 t = p * 0.859375 + sum2 * -0.1171875 + sum1 * -0.09765625;)
GLSLF("color = p + t * %f;\n", param);
GLSLF("}\n");
diff --git a/video/out/opengl/video_shaders.h b/video/out/opengl/video_shaders.h
index bbfeebb576..1f4496fbab 100644
--- a/video/out/opengl/video_shaders.h
+++ b/video/out/opengl/video_shaders.h
@@ -38,8 +38,9 @@ void pass_sample_oversample(struct gl_shader_cache *sc, struct scaler *scaler,
void pass_linearize(struct gl_shader_cache *sc, enum mp_csp_trc trc);
void pass_delinearize(struct gl_shader_cache *sc, enum mp_csp_trc trc);
+
void pass_sample_deband(struct gl_shader_cache *sc, struct deband_opts *opts,
- int tex_num, float tex_mul, GLenum tex_target, AVLFG *lfg);
+ AVLFG *lfg);
void pass_sample_unsharp(struct gl_shader_cache *sc, float param);