From 746a514529c753c3e2291ac991dbccb74b134c63 Mon Sep 17 00:00:00 2001 From: bloc97 Date: Wed, 14 Aug 2019 21:01:21 -0400 Subject: [PATCH] update glsl --- GLSL_Instructions.md | 11 ++ HLSL_Instructions.md | 2 +- README.md | 5 + glsl/Anime4K_Adaptive.glsl | 281 +++++++++++++++++++++++++++++++++++++ 4 files changed, 298 insertions(+), 1 deletion(-) create mode 100644 GLSL_Instructions.md create mode 100644 glsl/Anime4K_Adaptive.glsl diff --git a/GLSL_Instructions.md b/GLSL_Instructions.md new file mode 100644 index 00000000..eed526aa --- /dev/null +++ b/GLSL_Instructions.md @@ -0,0 +1,11 @@ + +# Usage Instructions (GLSL / MPV) +*If you wish to use another media player, look at their documentation on how to install GLSL shaders and modify the shader accordingly if needed.* + +1- Install [**mpv**](https://mpv.io/) +2- Download the .glsl shader files [**here**](https://github.com/bloc97/Anime4K/releases/download/0.9/Anime4K_GLSL.zip) +3- Copy the .glsl files to `%AppData%\mpv\shaders` for Windows or `~/.config/mpv/shaders` for Linux. +4- If `mpv.conf` does not exist in `%AppData%\mpv\` or `~/.config/mpv`, create a empty file and follow [**these instructions**](https://wiki.archlinux.org/index.php/Mpv#Configuration) to optimize your configuration. +5- Add this line to `mpv.conf` to enable the shaders: `glsl-shaders="~~/shaders/Anime4K_Adaptive.glsl"` + +*Unlike HLSL, the GLSL shader can auto-detect the scaling factor and adjust its strength accordingly.* diff --git a/HLSL_Instructions.md b/HLSL_Instructions.md index 67a51dda..7defb9da 100644 --- a/HLSL_Instructions.md +++ b/HLSL_Instructions.md @@ -1,6 +1,6 @@ # Usage Instructions (HLSL) -*If you wish to use another media player, look at their documentation on how to install HLSL shaders.* +*If you wish to use another media player, look at their documentation on how to install HLSL shaders and modify the shader accordingly if needed.* 1- Install [**MPC-BE**](https://sourceforge.net/projects/mpcbe/) and [madVR](http://madvr.com/) (Optional, but good for quality) 2- Download the .hlsl shader files [**here**](https://github.com/bloc97/Anime4K/releases/download/0.9/Anime4K_HLSL.zip) diff --git a/README.md b/README.md index 931cba74..118ca536 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,11 @@ Anime4K is a state-of-the-art open-source high-quality real-time anime upscaling # [HLSL Installation](HLSL_Instructions.md) Note for developpers: For performance, the HLSL shaders use the Alpha channel to store the gradient, you might need to make a backup of the the alpha channel before applying these shaders and restore it after if your rendering engine uses the alpha channel for other purposes. (In MPC-BE's case, it gets ignored.) +# GLSL Usage Instructions (MPV) +**Cross platform** +# [GLSL Installation](GLSL_Instructions.md) +Note for developpers: For performance, the GLSL shaders use the `POSTKERNEL` texture to store the gradient, you might need to make a backup of the the `POSTKERNEL` texture before applying these shaders and restore it after if your other shaders or rendering engine uses the `POSTKERNEL` texture for other purposes. (In MPV's case, it gets ignored.) + # Java Usage Instructions (Standalone) # [Java Installation](Java_Instructions.md) diff --git a/glsl/Anime4K_Adaptive.glsl b/glsl/Anime4K_Adaptive.glsl new file mode 100644 index 00000000..fd600de0 --- /dev/null +++ b/glsl/Anime4K_Adaptive.glsl @@ -0,0 +1,281 @@ + +//!HOOK SCALED +//!BIND HOOKED +//!BIND POSTKERNEL +//!SAVE POSTKERNEL + +float getLum(vec4 rgb) { + return (rgb.r + rgb.r + rgb.g + rgb.g + rgb.g + rgb.b) / 6; +} + +vec4 hook() { //Save lum on POSTKERNEL + vec4 rgb = HOOKED_tex(HOOKED_pos); + float lum = getLum(rgb); + return vec4(lum); +} + + +//!HOOK SCALED +//!BIND HOOKED +//!BIND POSTKERNEL +//!BIND NATIVE + +#define strength ((SCALED_size.x) / (NATIVE_size.x) / 6) + +vec4 getLargest(vec4 cc, vec4 lightestColor, vec4 a, vec4 b, vec4 c) { + vec4 newColor = cc * (1 - strength) + ((a + b + c) / 3) * strength; + if (newColor.a > lightestColor.a) { + return newColor; + } + return lightestColor; +} + +vec4 getRGBL(vec2 pos) { + return vec4(HOOKED_tex(pos).rgb, POSTKERNEL_tex(pos).x); +} + +float min3v(vec4 a, vec4 b, vec4 c) { + return min(min(a.a, b.a), c.a); +} +float max3v(vec4 a, vec4 b, vec4 c) { + return max(max(a.a, b.a), c.a); +} + + +vec4 hook() { + vec2 d = HOOKED_pt; + + vec4 cc = getRGBL(HOOKED_pos); + vec4 t = getRGBL(HOOKED_pos + vec2(0, -d.y)); + vec4 tl = getRGBL(HOOKED_pos + vec2(-d.x, -d.y)); + vec4 tr = getRGBL(HOOKED_pos + vec2(d.x, -d.y)); + + vec4 l = getRGBL(HOOKED_pos + vec2(-d.x, 0)); + vec4 r = getRGBL(HOOKED_pos + vec2(d.x, 0)); + + vec4 b = getRGBL(HOOKED_pos + vec2(0, d.y)); + vec4 bl = getRGBL(HOOKED_pos + vec2(-d.x, d.y)); + vec4 br = getRGBL(HOOKED_pos + vec2(d.x, d.y)); + + vec4 lightestColor = cc; + + //Kernel 0 and 4 + float maxDark = max3v(br, b, bl); + float minLight = min3v(tl, t, tr); + + if (minLight > cc.a && minLight > maxDark) { + lightestColor = getLargest(cc, lightestColor, tl, t, tr); + } else { + maxDark = max3v(tl, t, tr); + minLight = min3v(br, b, bl); + if (minLight > cc.a && minLight > maxDark) { + lightestColor = getLargest(cc, lightestColor, br, b, bl); + } + } + + //Kernel 1 and 5 + maxDark = max3v(cc, l, b); + minLight = min3v(r, t, tr); + + if (minLight > maxDark) { + lightestColor = getLargest(cc, lightestColor, r, t, tr); + } else { + maxDark = max3v(cc, r, t); + minLight = min3v(bl, l, b); + if (minLight > maxDark) { + lightestColor = getLargest(cc, lightestColor, bl, l, b); + } + } + + //Kernel 2 and 6 + maxDark = max3v(l, tl, bl); + minLight = min3v(r, br, tr); + + if (minLight > cc.a && minLight > maxDark) { + lightestColor = getLargest(cc, lightestColor, r, br, tr); + } else { + maxDark = max3v(r, br, tr); + minLight = min3v(l, tl, bl); + if (minLight > cc.a && minLight > maxDark) { + lightestColor = getLargest(cc, lightestColor, l, tl, bl); + } + } + + //Kernel 3 and 7 + maxDark = max3v(cc, l, t); + minLight = min3v(r, br, b); + + if (minLight > maxDark) { + lightestColor = getLargest(cc, lightestColor, r, br, b); + } else { + maxDark = max3v(cc, r, b); + minLight = min3v(t, l, tl); + if (minLight > maxDark) { + lightestColor = getLargest(cc, lightestColor, t, l, tl); + } + } + + + return lightestColor; +} + + +//!HOOK SCALED +//!BIND HOOKED +//!BIND POSTKERNEL +//!SAVE POSTKERNEL + +float getLum(vec4 rgb) { + return (rgb.r + rgb.r + rgb.g + rgb.g + rgb.g + rgb.b) / 6; +} + +vec4 hook() { //Save lum on POSTKERNEL + vec4 rgb = HOOKED_tex(HOOKED_pos); + float lum = getLum(rgb); + return vec4(lum); +} + + +//!HOOK SCALED +//!BIND HOOKED +//!BIND POSTKERNEL +//!SAVE POSTKERNEL + +vec4 getRGBL(vec2 pos) { + return vec4(HOOKED_tex(pos).rgb, POSTKERNEL_tex(pos).x); +} + +vec4 hook() { //Save grad on POSTKERNEL + vec2 d = HOOKED_pt; + + //[tl t tr] + //[ l cc r] + //[bl b br] + vec4 cc = getRGBL(HOOKED_pos); + vec4 t = getRGBL(HOOKED_pos + vec2(0, -d.y)); + vec4 tl = getRGBL(HOOKED_pos + vec2(-d.x, -d.y)); + vec4 tr = getRGBL(HOOKED_pos + vec2(d.x, -d.y)); + + vec4 l = getRGBL(HOOKED_pos + vec2(-d.x, 0)); + vec4 r = getRGBL(HOOKED_pos + vec2(d.x, 0)); + + vec4 b = getRGBL(HOOKED_pos + vec2(0, d.y)); + vec4 bl = getRGBL(HOOKED_pos + vec2(-d.x, d.y)); + vec4 br = getRGBL(HOOKED_pos + vec2(d.x, d.y)); + + + //Horizontal Gradient + //[-1 0 1] + //[-2 0 2] + //[-1 0 1] + float xgrad = (-tl.a + tr.a - l.a - l.a + r.a + r.a - bl.a + br.a); + + //Vertical Gradient + //[-1 -2 -1] + //[ 0 0 0] + //[ 1 2 1] + float ygrad = (-tl.a - t.a - t.a - tr.a + bl.a + b.a + b.a + br.a); + + //Computes the luminance's gradient and saves it in the unused alpha channel + return vec4(1 - clamp(sqrt(xgrad * xgrad + ygrad * ygrad), 0, 1)); +} + + + +//!HOOK SCALED +//!BIND HOOKED +//!BIND POSTKERNEL +//!BIND NATIVE + +#define strength ((SCALED_size.x) / (NATIVE_size.x) / 2) + +vec4 getAverage(vec4 cc, vec4 a, vec4 b, vec4 c) { + return cc * (1 - strength) + ((a + b + c) / 3) * strength; +} + +vec4 getRGBL(vec2 pos) { + return vec4(HOOKED_tex(pos).rgb, POSTKERNEL_tex(pos).x); +} + +float min3v(vec4 a, vec4 b, vec4 c) { + return min(min(a.a, b.a), c.a); +} +float max3v(vec4 a, vec4 b, vec4 c) { + return max(max(a.a, b.a), c.a); +} + + +vec4 hook() { + vec2 d = HOOKED_pt; + + vec4 cc = getRGBL(HOOKED_pos); + vec4 t = getRGBL(HOOKED_pos + vec2(0, -d.y)); + vec4 tl = getRGBL(HOOKED_pos + vec2(-d.x, -d.y)); + vec4 tr = getRGBL(HOOKED_pos + vec2(d.x, -d.y)); + + vec4 l = getRGBL(HOOKED_pos + vec2(-d.x, 0)); + vec4 r = getRGBL(HOOKED_pos + vec2(d.x, 0)); + + vec4 b = getRGBL(HOOKED_pos + vec2(0, d.y)); + vec4 bl = getRGBL(HOOKED_pos + vec2(-d.x, d.y)); + vec4 br = getRGBL(HOOKED_pos + vec2(d.x, d.y)); + + //Kernel 0 and 4 + float maxDark = max3v(br, b, bl); + float minLight = min3v(tl, t, tr); + + if (minLight > cc.a && minLight > maxDark) { + return getAverage(cc, tl, t, tr); + } else { + maxDark = max3v(tl, t, tr); + minLight = min3v(br, b, bl); + if (minLight > cc.a && minLight > maxDark) { + return getAverage(cc, br, b, bl); + } + } + + //Kernel 1 and 5 + maxDark = max3v(cc, l, b); + minLight = min3v(r, t, tr); + + if (minLight > maxDark) { + return getAverage(cc, r, t, tr); + } else { + maxDark = max3v(cc, r, t); + minLight = min3v(bl, l, b); + if (minLight > maxDark) { + return getAverage(cc, bl, l, b); + } + } + + //Kernel 2 and 6 + maxDark = max3v(l, tl, bl); + minLight = min3v(r, br, tr); + + if (minLight > cc.a && minLight > maxDark) { + return getAverage(cc, r, br, tr); + } else { + maxDark = max3v(r, br, tr); + minLight = min3v(l, tl, bl); + if (minLight > cc.a && minLight > maxDark) { + return getAverage(cc, l, tl, bl); + } + } + + //Kernel 3 and 7 + maxDark = max3v(cc, l, t); + minLight = min3v(r, br, b); + + if (minLight > maxDark) { + return getAverage(cc, r, br, b); + } else { + maxDark = max3v(cc, r, b); + minLight = min3v(t, l, tl); + if (minLight > maxDark) { + return getAverage(cc, t, l, tl); + } + } + + + return cc; +}