diff options
-rw-r--r-- | DOCS/man/vo.rst | 16 | ||||
-rw-r--r-- | video/out/opengl/nnedi3.c | 33 | ||||
-rw-r--r-- | video/out/opengl/nnedi3.h | 6 | ||||
-rw-r--r-- | video/out/opengl/superxbr.c | 29 | ||||
-rw-r--r-- | video/out/opengl/superxbr.h | 2 | ||||
-rw-r--r-- | video/out/opengl/video.c | 129 | ||||
-rw-r--r-- | video/out/opengl/video_shaders.c | 57 | ||||
-rw-r--r-- | video/out/opengl/video_shaders.h | 3 |
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, ¶ms[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); |