aboutsummaryrefslogtreecommitdiff
path: root/mpv/shaders/SSimDownscaler.glsl
diff options
context:
space:
mode:
authorTyler Hoang <tyler@tylerhoang.xyz>2022-09-06 17:12:49 -0700
committerTyler Hoang <tyler@tylerhoang.xyz>2022-09-06 17:12:49 -0700
commit9868de7f26cd336ae40a1f07827285b07d3dafd3 (patch)
tree0a4ef79c0a5b8b9eb5df229c00360f8db3ae27e8 /mpv/shaders/SSimDownscaler.glsl
parent81f6c74c871144aa79628095e735e35affd79f74 (diff)
mpv and vifmHEADmaster
Diffstat (limited to 'mpv/shaders/SSimDownscaler.glsl')
-rw-r--r--mpv/shaders/SSimDownscaler.glsl214
1 files changed, 214 insertions, 0 deletions
diff --git a/mpv/shaders/SSimDownscaler.glsl b/mpv/shaders/SSimDownscaler.glsl
new file mode 100644
index 0000000..1cc0ff7
--- /dev/null
+++ b/mpv/shaders/SSimDownscaler.glsl
@@ -0,0 +1,214 @@
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3.0 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library.
+
+//!HOOK POSTKERNEL
+//!BIND HOOKED
+//!BIND PREKERNEL
+//!SAVE L2
+//!WIDTH NATIVE_CROPPED.w
+//!WHEN NATIVE_CROPPED.h POSTKERNEL.h >
+//!COMPONENTS 3
+//!DESC SSimDownscaler L2 pass 1
+
+#define axis 1
+
+#define offset vec2(0,0)
+
+#define MN(B,C,x) (x < 1.0 ? ((2.-1.5*B-(C))*x + (-3.+2.*B+C))*x*x + (1.-(B)/3.) : (((-(B)/6.-(C))*x + (B+5.*C))*x + (-2.*B-8.*C))*x+((4./3.)*B+4.*C))
+#define Kernel(x) MN(.0, .5, abs(x))
+#define taps 2.0
+
+vec4 hook() {
+ vec2 base = PREKERNEL_pt * (PREKERNEL_pos * input_size + tex_offset);
+
+ float low = ceil((PREKERNEL_pos - taps*POSTKERNEL_pt) * input_size - offset + tex_offset - 0.5)[axis];
+ float high = floor((PREKERNEL_pos + taps*POSTKERNEL_pt) * input_size - offset + tex_offset - 0.5)[axis];
+
+ float W = 0.0;
+ vec4 avg = vec4(0);
+ vec2 pos = base;
+
+ for (float k = low; k <= high; k++) {
+ pos[axis] = PREKERNEL_pt[axis] * (k - offset[axis] + 0.5);
+ float rel = (pos[axis] - base[axis])*POSTKERNEL_size[axis];
+ float w = Kernel(rel);
+
+ vec4 tex = textureLod(PREKERNEL_raw, pos, 0.0) * PREKERNEL_mul;
+ avg += w * tex * tex;
+ W += w;
+ }
+ avg /= W;
+
+ return avg;
+}
+
+//!HOOK POSTKERNEL
+//!BIND HOOKED
+//!BIND L2
+//!SAVE L2
+//!WHEN NATIVE_CROPPED.w POSTKERNEL.w >
+//!COMPONENTS 3
+//!DESC SSimDownscaler L2 pass 2
+
+#define axis 0
+
+#define offset vec2(0,0)
+
+#define MN(B,C,x) (x < 1.0 ? ((2.-1.5*B-(C))*x + (-3.+2.*B+C))*x*x + (1.-(B)/3.) : (((-(B)/6.-(C))*x + (B+5.*C))*x + (-2.*B-8.*C))*x+((4./3.)*B+4.*C))
+#define Kernel(x) MN(.0, .5, abs(x))
+#define taps 2.0
+
+vec4 hook() {
+ float low = ceil((L2_pos - taps*POSTKERNEL_pt) * L2_size - offset - 0.5)[axis];
+ float high = floor((L2_pos + taps*POSTKERNEL_pt) * L2_size - offset - 0.5)[axis];
+
+ float W = 0.0;
+ vec4 avg = vec4(0);
+ vec2 pos = L2_pos;
+
+ for (float k = low; k <= high; k++) {
+ pos[axis] = L2_pt[axis] * (k - offset[axis] + 0.5);
+ float rel = (pos[axis] - L2_pos[axis])*POSTKERNEL_size[axis];
+ float w = Kernel(rel);
+
+ avg += w * textureLod(L2_raw, pos, 0.0) * L2_mul;
+ W += w;
+ }
+ avg /= W;
+
+ return avg;
+}
+
+//!HOOK POSTKERNEL
+//!BIND HOOKED
+//!BIND L2
+//!SAVE MR
+//!WHEN NATIVE_CROPPED.h POSTKERNEL.h >
+//!COMPONENTS 4
+//!DESC SSimDownscaler mean & R
+
+#define oversharp 0.0
+
+#define sigma_nsq 10. / (255.*255.)
+#define locality 2.0
+
+#define offset vec2(0,0)
+
+#define Kernel(x) pow(1.0 / locality, abs(x))
+#define taps 3.0
+
+#define Luma(rgb) ( dot(rgb, vec3(0.2126, 0.7152, 0.0722)) )
+
+mat3x3 ScaleH(vec2 pos) {
+ float low = ceil(-0.5*taps - offset)[0];
+ float high = floor(0.5*taps - offset)[0];
+
+ float W = 0.0;
+ mat3x3 avg = mat3x3(0);
+
+ for (float k = low; k <= high; k++) {
+ pos[0] = HOOKED_pos[0] + HOOKED_pt[0] * k;
+ float rel = k + offset[0];
+ float w = Kernel(rel);
+
+ vec3 L = POSTKERNEL_tex(pos).rgb;
+ avg += w * mat3x3(L, L*L, L2_tex(pos).rgb);
+ W += w;
+ }
+ avg /= W;
+
+ return avg;
+}
+
+vec4 hook() {
+ vec2 pos = HOOKED_pos;
+
+ float low = ceil(-0.5*taps - offset)[1];
+ float high = floor(0.5*taps - offset)[1];
+
+ float W = 0.0;
+ mat3x3 avg = mat3x3(0);
+
+ for (float k = low; k <= high; k++) {
+ pos[1] = HOOKED_pos[1] + HOOKED_pt[1] * k;
+ float rel = k + offset[1];
+ float w = Kernel(rel);
+
+ avg += w * ScaleH(pos);
+ W += w;
+ }
+ avg /= W;
+
+ float Sl = Luma(max(avg[1] - avg[0] * avg[0], 0.));
+ float Sh = Luma(max(avg[2] - avg[0] * avg[0], 0.));
+ return vec4(avg[0], mix(sqrt((Sh + sigma_nsq) / (Sl + sigma_nsq)) * (1. + oversharp), clamp(Sh / Sl, 0., 1.), int(Sl > Sh)));
+}
+
+//!HOOK POSTKERNEL
+//!BIND HOOKED
+//!BIND MR
+//!WHEN NATIVE_CROPPED.h POSTKERNEL.h >
+//!DESC SSimDownscaler final pass
+
+#define locality 2.0
+
+#define offset vec2(0,0)
+
+#define Kernel(x) pow(1.0 / locality, abs(x))
+#define taps 3.0
+
+#define Gamma(x) ( pow(x, vec3(1.0/2.0)) )
+#define GammaInv(x) ( pow(clamp(x, 0.0, 1.0), vec3(2.0)) )
+
+mat3x3 ScaleH(vec2 pos) {
+ float low = ceil(-0.5*taps - offset)[0];
+ float high = floor(0.5*taps - offset)[0];
+
+ float W = 0.0;
+ mat3x3 avg = mat3x3(0);
+
+ for (float k = low; k <= high; k++) {
+ pos[0] = HOOKED_pos[0] + HOOKED_pt[0] * k;
+ float rel = k + offset[0];
+ float w = Kernel(rel);
+
+ vec4 MR = MR_tex(pos);
+ avg += w * mat3x3(MR.a*MR.rgb, MR.rgb, MR.aaa);
+ W += w;
+ }
+ avg /= W;
+
+ return avg;
+}
+
+vec4 hook() {
+ vec2 pos = HOOKED_pos;
+
+ float low = ceil(-0.5*taps - offset)[1];
+ float high = floor(0.5*taps - offset)[1];
+
+ float W = 0.0;
+ mat3x3 avg = mat3x3(0);
+
+ for (float k = low; k <= high; k++) {
+ pos[1] = HOOKED_pos[1] + HOOKED_pt[1] * k;
+ float rel = k + offset[1];
+ float w = Kernel(rel);
+
+ avg += w * ScaleH(pos);
+ W += w;
+ }
+ avg /= W;
+ vec4 L = POSTKERNEL_texOff(0);
+ return vec4(avg[1] + avg[2] * L.rgb - avg[0], L.a);
+}