diff --git a/.config/mpv/input.conf b/.config/mpv/input.conf index 5cb99e6..bb741e8 100755 --- a/.config/mpv/input.conf +++ b/.config/mpv/input.conf @@ -1 +1 @@ -d script-message cycle-profiles "bwdifdeint;deinterlace-no" \ No newline at end of file +#d script-message cycle-profiles "bwdifdeint;deinterlace-no" diff --git a/.config/mpv/mpv.conf b/.config/mpv/mpv.conf index d880db0..3e0af28 100755 --- a/.config/mpv/mpv.conf +++ b/.config/mpv/mpv.conf @@ -2,20 +2,51 @@ #Mitchell-Netravali. The B and C parameters can be set with --scale-param1 and #--scale-param2. This filter is very good at downscaling (see --dscale). -scale=mitchell -#Mid quality and speed. This is the default when using gpu-hq. -#scale=spline36 +#catmull_rom uses less resources than lanczos +#spline36 is kinda bad, for upscaling you should use bicubic catrom for preserving spatial proerties +#or a lanczos scaler (like ewa_lanczos or ewa_lanczossharp) for sharpness -#mitchell uses less resources than spline36 -#spline36 looks slightly better -#mitchell = bicubic b 0.33 c 0.33 +#catmull_rom = bicubic b 0 c 0.5 +#mitchell = bicubic b 1/3 c 1/3 +#hermite = bicubic b 0 c 0 + +scale=catmull_rom #--dscale= #Like --scale, but apply these filters on downscaling instead. #If this option is unset, the filter implied by --scale will be applied. -#dscale=spline36 -dscale=mitchell + +#due to how negative lobes work, mitchell and hermite perform much better for downscaling (less ringing and aliasing) +#hermite is sharper than mitchell +#https://github.com/mpv-player/mpv/pull/12384#issuecomment-1716775594 +#https://github.com/mpv-player/mpv/pull/12384#issuecomment-1716855374 + +dscale=hermite + + +#catmull_rom, sinc(blackman), ewa_hanning +#For a traditional scaler, is better to use sinc, but it has random performance spikes and +#more resource usage than catmull_rom +cscale=sinc +cscale-window=blackman #for sinc +cscale-radius=3 #for sinc + +#you can also use 'FastBilateral', 'JointBilateral', 'MemeBilateral' or KrigBilateral +#(less to more quality and performance) meme shaders for better chroma +#FastBilateral and JointBilateral may have staircase artifacts +#MemeBilateral is JointBilateral with + CfL (Chroma from Luma prediction), so you can also use FastBilateral and CfL together for better performance +glsl-shader="~~/shaders/FastBilateral.glsl" +#glsl-shader="~~/shaders/CfL_Prediction.glsl" + +#there are memes about bilinear cscale being the true way the encoder and encoding software +#intended the chroma to be watched, if you believe them or not is up to you +#cscale=bilinear + + +#you can use sphinx (smoother) or oversample (less blurry), not a fan of them +#tscale=sphinx +#tscale-blur=0.6991556596428412 #magic haasn number for sphinx @@ -27,6 +58,9 @@ dscale=mitchell #Audio output drivers are interfaces to different audio output facilities. ao=pipewire,coreauido,pulse,wasapi, +#Load external audio with (almost) the same name as the video +audio-file-auto=fuzzy + volume=100 volume-max=200 @@ -47,6 +81,8 @@ audio-exclusive=no # OTHER +sub-auto=fuzzy + #user-agent="Mozilla/5.0" @@ -88,18 +124,32 @@ screenshot-png-filter=0 # HDR TONE MAPPING +dither=fruit -hdr-compute-peak=no +dither-depth=8 -#tone-mapping=hable +#dither-size-fruit=8 -#tone-mapping-param=0.6 +#common primaries for modern displays are 'bt.709' (sRGB), 'bt.2020', 'apple' (Apple RGB), 'adobe' (Adobe RGB), 'dci-p3' +target-prim=bt.709 + +# transfer characteristics (gamma), you can leave it on 'auto', you can also use 'bt.1886', 'srgb', 'linear', 'pq' or another option +target-trc=srgb + +#you can leave it on 'auto', sdr is '203' +target-peak=auto + +hdr-compute-peak=yes + +allow-delayed-peak-detect=yes #better performance tone-mapping=bt.2390 #tone-mapping-param=1.5 -tone-mapping-mode=hybrid +hdr-peak-percentile=100 #better leave it at 100 + +#tone-mapping-mode=hybrid #deprecated https://github.com/mpv-player/mpv/commit/b4c98cb04c87999eccd061cc59e6f5f8fa706220 gamut-mapping-mode=darken @@ -111,6 +161,7 @@ icc-intent=0 + # DEBANDING @@ -124,26 +175,33 @@ deband=no #vulkan uses more resources,but has better hdr compatibility #if you use d3d11va-copy without opengl or vulkan, it may lead to video/audio desync #gpu-api=opengl # Uncomment this if you notice stuttering with vulkan, opengl may cause screen tearing depending of your config -gpu-api=vulkan # Comment this if you notice stuttering and uncomment the above line +#gpu-api=vulkan # Comment this if you notice stuttering and uncomment the above line +#gpu-context=winvk vulkan-async-compute=yes vulkan-async-transfer=yes vulkan-queue-count=1 vulkan-device='Intel(R) UHD Graphics 620' +#vulkan-device='NVIDIA GeForce MX110' #opengl-waitvsync=yes vd-lavc-dr=yes #i think this solves screen tearing when using gpu-api=opengl spirv-compiler=auto -#hwdec=auto-safe -#hwdec=auto-copy -hwdec=d3d11va-copy #windows only, auto-copy uses dxva2-copy instead of d3d11va-copy, but d3d11va-copy is better and has better color +hwdec=auto-safe +#hwdec=auto-copy-safe +#hwdec=vaapi +#hwdec=vulkan +#hwdec=d3d11va-copy #windows only, auto-copy uses dxva2-copy instead of d3d11va-copy, but d3d11va-copy is better and has better color +#hwdec=vaapi-copy + +#interpolation=yes #interpolation-threshold=-1 #video-sync=display-resample -video-sync=audio #fix desync on d3d11va-copy when not using opengl or vulkan +video-sync=audio #fix desync on d3d11va-copy when not using gpu-api = opengl or vulkan #gpu has better performance but gpu-next has better hdr -vo=gpu -#vo=gpu-next +#vo=gpu +vo=gpu-next @@ -172,4 +230,4 @@ vf-clr #[bwdifdeint-autoprofile] #profile-cond=p["video-format/tff"] -#profile=bwdifdeint \ No newline at end of file +#profile=bwdifdeint diff --git a/.config/mpv/shaders/CfL_Prediction.glsl b/.config/mpv/shaders/CfL_Prediction.glsl new file mode 100755 index 0000000..8a84d85 --- /dev/null +++ b/.config/mpv/shaders/CfL_Prediction.glsl @@ -0,0 +1,249 @@ +// MIT License + +// Copyright (c) 2023 João Chrisóstomo + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +//!HOOK CHROMA +//!BIND CHROMA +//!BIND LUMA +//!SAVE LUMA_LOWRES +//!WIDTH CHROMA.w +//!HEIGHT LUMA.h +//!WHEN CHROMA.w LUMA.w < +//!DESC Chroma From Luma Prediction (Downscaling Luma 1st Step) + +vec4 hook() { + float factor = ceil(LUMA_size.x / CHROMA_size.x); + int start = int(ceil(-factor - 0.5)); + int end = int(floor(factor - 0.5)); + float filter_end = float(end) + 1.5; + + float output_luma = 0.0; + float wt = 0.0; + for (int dx = start; dx <= end; dx++) { + float luma_pix = LUMA_texOff(vec2(dx + 0.5, 0.0)).x; + float wd = smoothstep(0.0, filter_end, filter_end - length(vec2(dx + 0.5, 0.0))); + output_luma += luma_pix * wd; + wt += wd; + } + vec4 output_pix = vec4(output_luma / wt, 0.0, 0.0, 1.0); + return output_pix; +} + +//!HOOK CHROMA +//!BIND CHROMA +//!BIND LUMA_LOWRES +//!SAVE LUMA_LOWRES +//!WIDTH CHROMA.w +//!HEIGHT CHROMA.h +//!WHEN CHROMA.w LUMA.w < +//!DESC Chroma From Luma Prediction (Downscaling Luma 2nd Step) + +vec4 hook() { + float factor = ceil(LUMA_LOWRES_size.y / CHROMA_size.y); + int start = int(ceil(-factor - 0.5)); + int end = int(floor(factor - 0.5)); + float filter_end = float(end) + 1.5; + + float output_luma = 0.0; + float wt = 0.0; + for (int dy = start; dy <= end; dy++) { + float luma_pix = LUMA_LOWRES_texOff(vec2(0.0, dy + 0.5)).x; + float wd = smoothstep(0.0, filter_end, filter_end - length(vec2(0.0, dy + 0.5))); + output_luma += luma_pix * wd; + wt += wd; + } + vec4 output_pix = vec4(output_luma / wt, 0.0, 0.0, 1.0); + return output_pix; +} + +//!HOOK CHROMA +//!BIND CHROMA +//!BIND LUMA +//!BIND LUMA_LOWRES +//!WHEN CHROMA.w LUMA.w < +//!WIDTH LUMA.w +//!HEIGHT LUMA.h +//!OFFSET ALIGN +//!DESC Chroma From Luma Prediction (Upscaling Chroma) + +float comp_wd(vec2 distance) { + float d = min(length(distance), 2.0); + if (d < 1.0) { + return (6.0 + d * d * (-15.0 + d * 9.0)) / 6.0; + } else { + return (12.0 + d * (-24.0 + d * (15.0 + d * -3.0))) / 6.0; + } +} + +vec4 hook() { + float division_limit = 1e-4; + + vec4 output_pix = vec4(0.0, 0.0, 0.0, 1.0); + float luma_zero = LUMA_texOff(0.0).x; + + vec2 pp = CHROMA_pos * CHROMA_size - vec2(0.5); + vec2 fp = floor(pp); + pp -= fp; + + vec2 chroma_pixels[12]; + chroma_pixels[0] = CHROMA_tex(vec2((fp + vec2(0.5, -0.5)) * CHROMA_pt)).xy; + chroma_pixels[1] = CHROMA_tex(vec2((fp + vec2(1.5, -0.5)) * CHROMA_pt)).xy; + chroma_pixels[2] = CHROMA_tex(vec2((fp + vec2(-0.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[3] = CHROMA_tex(vec2((fp + vec2( 0.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[4] = CHROMA_tex(vec2((fp + vec2( 1.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[5] = CHROMA_tex(vec2((fp + vec2( 2.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[6] = CHROMA_tex(vec2((fp + vec2(-0.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[7] = CHROMA_tex(vec2((fp + vec2( 0.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[8] = CHROMA_tex(vec2((fp + vec2( 1.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[9] = CHROMA_tex(vec2((fp + vec2( 2.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[10] = CHROMA_tex(vec2((fp + vec2(0.5, 2.5) ) * CHROMA_pt)).xy; + chroma_pixels[11] = CHROMA_tex(vec2((fp + vec2(1.5, 2.5) ) * CHROMA_pt)).xy; + + float luma_pixels[12]; + luma_pixels[0] = LUMA_LOWRES_tex(vec2((fp + vec2(0.5, -0.5)) * CHROMA_pt)).x; + luma_pixels[1] = LUMA_LOWRES_tex(vec2((fp + vec2(1.5, -0.5)) * CHROMA_pt)).x; + luma_pixels[2] = LUMA_LOWRES_tex(vec2((fp + vec2(-0.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[3] = LUMA_LOWRES_tex(vec2((fp + vec2( 0.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[4] = LUMA_LOWRES_tex(vec2((fp + vec2( 1.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[5] = LUMA_LOWRES_tex(vec2((fp + vec2( 2.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[6] = LUMA_LOWRES_tex(vec2((fp + vec2(-0.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[7] = LUMA_LOWRES_tex(vec2((fp + vec2( 0.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[8] = LUMA_LOWRES_tex(vec2((fp + vec2( 1.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[9] = LUMA_LOWRES_tex(vec2((fp + vec2( 2.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[10] = LUMA_LOWRES_tex(vec2((fp + vec2(0.5, 2.5) ) * CHROMA_pt)).x; + luma_pixels[11] = LUMA_LOWRES_tex(vec2((fp + vec2(1.5, 2.5) ) * CHROMA_pt)).x; + + vec2 chroma_min = vec2(1e8); + chroma_min = min(chroma_min, chroma_pixels[3]); + chroma_min = min(chroma_min, chroma_pixels[4]); + chroma_min = min(chroma_min, chroma_pixels[7]); + chroma_min = min(chroma_min, chroma_pixels[8]); + + vec2 chroma_max = vec2(1e-8); + chroma_max = max(chroma_max, chroma_pixels[3]); + chroma_max = max(chroma_max, chroma_pixels[4]); + chroma_max = max(chroma_max, chroma_pixels[7]); + chroma_max = max(chroma_max, chroma_pixels[8]); + + float wd[12]; + wd[0] = comp_wd(vec2( 0.0,-1.0) - pp); + wd[1] = comp_wd(vec2( 1.0,-1.0) - pp); + wd[2] = comp_wd(vec2(-1.0, 0.0) - pp); + wd[3] = comp_wd(vec2( 0.0, 0.0) - pp); + wd[4] = comp_wd(vec2( 1.0, 0.0) - pp); + wd[5] = comp_wd(vec2( 2.0, 0.0) - pp); + wd[6] = comp_wd(vec2(-1.0, 1.0) - pp); + wd[7] = comp_wd(vec2( 0.0, 1.0) - pp); + wd[8] = comp_wd(vec2( 1.0, 1.0) - pp); + wd[9] = comp_wd(vec2( 2.0, 1.0) - pp); + wd[10] = comp_wd(vec2( 0.0, 2.0) - pp); + wd[11] = comp_wd(vec2( 1.0, 2.0) - pp); + + float wt = 0.0; + for (int i = 0; i < 12; i++) { + wt += wd[i]; + } + + vec2 ct = vec2(0.0); + for (int i = 0; i < 12; i++) { + ct += wd[i] * chroma_pixels[i]; + } + + vec2 chroma_spatial = ct / wt; + chroma_spatial = clamp(chroma_spatial, chroma_min, chroma_max); + + float luma_avg_4 = 0.0; + luma_avg_4 += luma_pixels[3]; + luma_avg_4 += luma_pixels[4]; + luma_avg_4 += luma_pixels[7]; + luma_avg_4 += luma_pixels[8]; + luma_avg_4 /= 4.0; + + float luma_var_4 = 0.0; + luma_var_4 += pow(luma_pixels[3] - luma_avg_4, 2.0); + luma_var_4 += pow(luma_pixels[4] - luma_avg_4, 2.0); + luma_var_4 += pow(luma_pixels[7] - luma_avg_4, 2.0); + luma_var_4 += pow(luma_pixels[8] - luma_avg_4, 2.0); + + vec2 chroma_avg_4 = vec2(0.0); + chroma_avg_4 += chroma_pixels[3]; + chroma_avg_4 += chroma_pixels[4]; + chroma_avg_4 += chroma_pixels[7]; + chroma_avg_4 += chroma_pixels[8]; + chroma_avg_4 /= 4.0; + + vec2 luma_chroma_cov_4 = vec2(0.0); + luma_chroma_cov_4 += (luma_pixels[3] - luma_avg_4) * (chroma_pixels[3] - chroma_avg_4); + luma_chroma_cov_4 += (luma_pixels[4] - luma_avg_4) * (chroma_pixels[4] - chroma_avg_4); + luma_chroma_cov_4 += (luma_pixels[7] - luma_avg_4) * (chroma_pixels[7] - chroma_avg_4); + luma_chroma_cov_4 += (luma_pixels[8] - luma_avg_4) * (chroma_pixels[8] - chroma_avg_4); + + vec2 alpha_4 = luma_chroma_cov_4 / max(luma_var_4, division_limit); + vec2 beta_4 = chroma_avg_4 - alpha_4 * luma_avg_4; + + vec2 chroma_pred_4 = alpha_4 * luma_zero + beta_4; + chroma_pred_4 = clamp(chroma_pred_4, 0.0, 1.0); + + float luma_avg_12 = 0.0; + for(int i = 0; i < 12; i++) { + luma_avg_12 += luma_pixels[i]; + } + luma_avg_12 /= 12.0; + + float luma_var_12 = 0.0; + for(int i = 0; i < 12; i++) { + luma_var_12 += pow(luma_pixels[i] - luma_avg_12, 2.0); + } + + vec2 chroma_avg_12 = vec2(0.0); + for(int i = 0; i < 12; i++) { + chroma_avg_12 += chroma_pixels[i]; + } + chroma_avg_12 /= 12.0; + + vec2 chroma_var_12 = vec2(0.0); + for(int i = 0; i < 12; i++) { + chroma_var_12 += pow(chroma_pixels[i] - chroma_avg_12, vec2(2.0)); + } + + vec2 luma_chroma_cov_12 = vec2(0.0); + for(int i = 0; i < 12; i++) { + luma_chroma_cov_12 += (luma_pixels[i] - luma_avg_12) * (chroma_pixels[i] - chroma_avg_12); + } + + vec2 corr = abs(luma_chroma_cov_12 / max(sqrt(luma_var_12 * chroma_var_12), division_limit)); + corr = clamp(corr, 0.0, 1.0); + + vec2 alpha_12 = luma_chroma_cov_12 / max(luma_var_12, division_limit); + vec2 beta_12 = chroma_avg_12 - alpha_12 * luma_avg_12; + + vec2 chroma_pred_12 = alpha_12 * luma_zero + beta_12; + chroma_pred_12 = clamp(chroma_pred_12, 0.0, 1.0); + + chroma_pred_4 = mix(chroma_spatial, chroma_pred_4, pow(corr, vec2(2.0)) / 2.0); + chroma_pred_12 = mix(chroma_spatial, chroma_pred_12, pow(corr, vec2(2.0)) / 2.0); + output_pix.xy = mix(chroma_pred_4, chroma_pred_12, 0.5); + + // Replace this with chroma_min and chroma_max if you want AR + // output_pix.yz = clamp(output_pix.yz, chroma_min, chroma_max); + output_pix.xy = clamp(output_pix.xy, 0.0, 1.0); + return output_pix; +} \ No newline at end of file diff --git a/.config/mpv/shaders/CfL_Prediction_12tap.glsl b/.config/mpv/shaders/CfL_Prediction_12tap.glsl new file mode 100755 index 0000000..c6677d4 --- /dev/null +++ b/.config/mpv/shaders/CfL_Prediction_12tap.glsl @@ -0,0 +1,215 @@ +// MIT License + +// Copyright (c) 2023 João Chrisóstomo + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +//!HOOK CHROMA +//!BIND CHROMA +//!BIND LUMA +//!SAVE LUMA_LOWRES +//!WIDTH CHROMA.w +//!HEIGHT LUMA.h +//!WHEN CHROMA.w LUMA.w < +//!DESC Chroma From Luma Prediction (Downscaling Luma 1st Step) + +vec4 hook() { + float factor = ceil(LUMA_size.x / CHROMA_size.x); + int start = int(ceil(-factor - 0.5)); + int end = int(floor(factor - 0.5)); + float filter_end = float(end) + 1.5; + + float output_luma = 0.0; + float wt = 0.0; + for (int dx = start; dx <= end; dx++) { + float luma_pix = LUMA_texOff(vec2(dx + 0.5, 0.0)).x; + float wd = smoothstep(0.0, filter_end, filter_end - length(vec2(dx + 0.5, 0.0))); + output_luma += luma_pix * wd; + wt += wd; + } + vec4 output_pix = vec4(output_luma / wt, 0.0, 0.0, 1.0); + return output_pix; +} + +//!HOOK CHROMA +//!BIND CHROMA +//!BIND LUMA_LOWRES +//!SAVE LUMA_LOWRES +//!WIDTH CHROMA.w +//!HEIGHT CHROMA.h +//!WHEN CHROMA.w LUMA.w < +//!DESC Chroma From Luma Prediction (Downscaling Luma 2nd Step) + +vec4 hook() { + float factor = ceil(LUMA_LOWRES_size.y / CHROMA_size.y); + int start = int(ceil(-factor - 0.5)); + int end = int(floor(factor - 0.5)); + float filter_end = float(end) + 1.5; + + float output_luma = 0.0; + float wt = 0.0; + for (int dy = start; dy <= end; dy++) { + float luma_pix = LUMA_LOWRES_texOff(vec2(0.0, dy + 0.5)).x; + float wd = smoothstep(0.0, filter_end, filter_end - length(vec2(0.0, dy + 0.5))); + output_luma += luma_pix * wd; + wt += wd; + } + vec4 output_pix = vec4(output_luma / wt, 0.0, 0.0, 1.0); + return output_pix; +} + +//!HOOK CHROMA +//!BIND CHROMA +//!BIND LUMA +//!BIND LUMA_LOWRES +//!WHEN CHROMA.w LUMA.w < +//!WIDTH LUMA.w +//!HEIGHT LUMA.h +//!OFFSET ALIGN +//!DESC Chroma From Luma Prediction (12-tap, Upscaling Chroma) + +float comp_wd(vec2 distance) { + float d = min(length(distance), 2.0); + if (d < 1.0) { + return (6.0 + d * d * (-15.0 + d * 9.0)) / 6.0; + } else { + return (12.0 + d * (-24.0 + d * (15.0 + d * -3.0))) / 6.0; + } +} + +vec4 hook() { + float division_limit = 1e-4; + + vec4 output_pix = vec4(0.0, 0.0, 0.0, 1.0); + float luma_zero = LUMA_texOff(0.0).x; + + vec2 pp = CHROMA_pos * CHROMA_size - vec2(0.5); + vec2 fp = floor(pp); + pp -= fp; + + vec2 chroma_pixels[12]; + chroma_pixels[0] = CHROMA_tex(vec2((fp + vec2(0.5, -0.5)) * CHROMA_pt)).xy; + chroma_pixels[1] = CHROMA_tex(vec2((fp + vec2(1.5, -0.5)) * CHROMA_pt)).xy; + chroma_pixels[2] = CHROMA_tex(vec2((fp + vec2(-0.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[3] = CHROMA_tex(vec2((fp + vec2( 0.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[4] = CHROMA_tex(vec2((fp + vec2( 1.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[5] = CHROMA_tex(vec2((fp + vec2( 2.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[6] = CHROMA_tex(vec2((fp + vec2(-0.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[7] = CHROMA_tex(vec2((fp + vec2( 0.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[8] = CHROMA_tex(vec2((fp + vec2( 1.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[9] = CHROMA_tex(vec2((fp + vec2( 2.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[10] = CHROMA_tex(vec2((fp + vec2(0.5, 2.5) ) * CHROMA_pt)).xy; + chroma_pixels[11] = CHROMA_tex(vec2((fp + vec2(1.5, 2.5) ) * CHROMA_pt)).xy; + + float luma_pixels[12]; + luma_pixels[0] = LUMA_LOWRES_tex(vec2((fp + vec2(0.5, -0.5)) * CHROMA_pt)).x; + luma_pixels[1] = LUMA_LOWRES_tex(vec2((fp + vec2(1.5, -0.5)) * CHROMA_pt)).x; + luma_pixels[2] = LUMA_LOWRES_tex(vec2((fp + vec2(-0.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[3] = LUMA_LOWRES_tex(vec2((fp + vec2( 0.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[4] = LUMA_LOWRES_tex(vec2((fp + vec2( 1.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[5] = LUMA_LOWRES_tex(vec2((fp + vec2( 2.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[6] = LUMA_LOWRES_tex(vec2((fp + vec2(-0.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[7] = LUMA_LOWRES_tex(vec2((fp + vec2( 0.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[8] = LUMA_LOWRES_tex(vec2((fp + vec2( 1.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[9] = LUMA_LOWRES_tex(vec2((fp + vec2( 2.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[10] = LUMA_LOWRES_tex(vec2((fp + vec2(0.5, 2.5) ) * CHROMA_pt)).x; + luma_pixels[11] = LUMA_LOWRES_tex(vec2((fp + vec2(1.5, 2.5) ) * CHROMA_pt)).x; + + vec2 chroma_min = vec2(1e8); + chroma_min = min(chroma_min, chroma_pixels[3]); + chroma_min = min(chroma_min, chroma_pixels[4]); + chroma_min = min(chroma_min, chroma_pixels[7]); + chroma_min = min(chroma_min, chroma_pixels[8]); + + vec2 chroma_max = vec2(1e-8); + chroma_max = max(chroma_max, chroma_pixels[3]); + chroma_max = max(chroma_max, chroma_pixels[4]); + chroma_max = max(chroma_max, chroma_pixels[7]); + chroma_max = max(chroma_max, chroma_pixels[8]); + + float wd[12]; + wd[0] = comp_wd(vec2( 0.0,-1.0) - pp); + wd[1] = comp_wd(vec2( 1.0,-1.0) - pp); + wd[2] = comp_wd(vec2(-1.0, 0.0) - pp); + wd[3] = comp_wd(vec2( 0.0, 0.0) - pp); + wd[4] = comp_wd(vec2( 1.0, 0.0) - pp); + wd[5] = comp_wd(vec2( 2.0, 0.0) - pp); + wd[6] = comp_wd(vec2(-1.0, 1.0) - pp); + wd[7] = comp_wd(vec2( 0.0, 1.0) - pp); + wd[8] = comp_wd(vec2( 1.0, 1.0) - pp); + wd[9] = comp_wd(vec2( 2.0, 1.0) - pp); + wd[10] = comp_wd(vec2( 0.0, 2.0) - pp); + wd[11] = comp_wd(vec2( 1.0, 2.0) - pp); + + float wt = 0.0; + for (int i = 0; i < 12; i++) { + wt += wd[i]; + } + + vec2 ct = vec2(0.0); + for (int i = 0; i < 12; i++) { + ct += wd[i] * chroma_pixels[i]; + } + + vec2 chroma_spatial = ct / wt; + chroma_spatial = clamp(chroma_spatial, chroma_min, chroma_max); + + float luma_avg_12 = 0.0; + for(int i = 0; i < 12; i++) { + luma_avg_12 += luma_pixels[i]; + } + luma_avg_12 /= 12.0; + + float luma_var_12 = 0.0; + for(int i = 0; i < 12; i++) { + luma_var_12 += pow(luma_pixels[i] - luma_avg_12, 2.0); + } + + vec2 chroma_avg_12 = vec2(0.0); + for(int i = 0; i < 12; i++) { + chroma_avg_12 += chroma_pixels[i]; + } + chroma_avg_12 /= 12.0; + + vec2 chroma_var_12 = vec2(0.0); + for(int i = 0; i < 12; i++) { + chroma_var_12 += pow(chroma_pixels[i] - chroma_avg_12, vec2(2.0)); + } + + vec2 luma_chroma_cov_12 = vec2(0.0); + for(int i = 0; i < 12; i++) { + luma_chroma_cov_12 += (luma_pixels[i] - luma_avg_12) * (chroma_pixels[i] - chroma_avg_12); + } + + vec2 corr = abs(luma_chroma_cov_12 / max(sqrt(luma_var_12 * chroma_var_12), division_limit)); + corr = clamp(corr, 0.0, 1.0); + + vec2 alpha_12 = luma_chroma_cov_12 / max(luma_var_12, division_limit); + vec2 beta_12 = chroma_avg_12 - alpha_12 * luma_avg_12; + + vec2 chroma_pred_12 = alpha_12 * luma_zero + beta_12; + chroma_pred_12 = clamp(chroma_pred_12, 0.0, 1.0); + + output_pix.xy = mix(chroma_spatial, chroma_pred_12, pow(corr, vec2(2.0)) / 2.0); + + // Replace this with chroma_min and chroma_max if you want AR + // output_pix.yz = clamp(output_pix.yz, chroma_min, chroma_max); + output_pix.xy = clamp(output_pix.xy, 0.0, 1.0); + return output_pix; +} \ No newline at end of file diff --git a/.config/mpv/shaders/CfL_Prediction_4tap.glsl b/.config/mpv/shaders/CfL_Prediction_4tap.glsl new file mode 100755 index 0000000..c0b3aab --- /dev/null +++ b/.config/mpv/shaders/CfL_Prediction_4tap.glsl @@ -0,0 +1,241 @@ +// MIT License + +// Copyright (c) 2023 João Chrisóstomo + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +//!HOOK CHROMA +//!BIND CHROMA +//!BIND LUMA +//!SAVE LUMA_LOWRES +//!WIDTH CHROMA.w +//!HEIGHT LUMA.h +//!WHEN CHROMA.w LUMA.w < +//!DESC Chroma From Luma Prediction (Downscaling Luma 1st Step) + +vec4 hook() { + float factor = ceil(LUMA_size.x / CHROMA_size.x); + int start = int(ceil(-factor - 0.5)); + int end = int(floor(factor - 0.5)); + float filter_end = float(end) + 1.5; + + float output_luma = 0.0; + float wt = 0.0; + for (int dx = start; dx <= end; dx++) { + float luma_pix = LUMA_texOff(vec2(dx + 0.5, 0.0)).x; + float wd = smoothstep(0.0, filter_end, filter_end - length(vec2(dx + 0.5, 0.0))); + output_luma += luma_pix * wd; + wt += wd; + } + vec4 output_pix = vec4(output_luma / wt, 0.0, 0.0, 1.0); + return output_pix; +} + +//!HOOK CHROMA +//!BIND CHROMA +//!BIND LUMA_LOWRES +//!SAVE LUMA_LOWRES +//!WIDTH CHROMA.w +//!HEIGHT CHROMA.h +//!WHEN CHROMA.w LUMA.w < +//!DESC Chroma From Luma Prediction (Downscaling Luma 2nd Step) + +vec4 hook() { + float factor = ceil(LUMA_LOWRES_size.y / CHROMA_size.y); + int start = int(ceil(-factor - 0.5)); + int end = int(floor(factor - 0.5)); + float filter_end = float(end) + 1.5; + + float output_luma = 0.0; + float wt = 0.0; + for (int dy = start; dy <= end; dy++) { + float luma_pix = LUMA_LOWRES_texOff(vec2(0.0, dy + 0.5)).x; + float wd = smoothstep(0.0, filter_end, filter_end - length(vec2(0.0, dy + 0.5))); + output_luma += luma_pix * wd; + wt += wd; + } + vec4 output_pix = vec4(output_luma / wt, 0.0, 0.0, 1.0); + return output_pix; +} + +//!HOOK CHROMA +//!BIND CHROMA +//!BIND LUMA +//!BIND LUMA_LOWRES +//!WHEN CHROMA.w LUMA.w < +//!WIDTH LUMA.w +//!HEIGHT LUMA.h +//!OFFSET ALIGN +//!DESC Chroma From Luma Prediction (4-tap, Upscaling Chroma) + +float comp_wd(vec2 distance) { + float d = min(length(distance), 2.0); + if (d < 1.0) { + return (6.0 + d * d * (-15.0 + d * 9.0)) / 6.0; + } else { + return (12.0 + d * (-24.0 + d * (15.0 + d * -3.0))) / 6.0; + } +} + +vec4 hook() { + float division_limit = 1e-4; + + vec4 output_pix = vec4(0.0, 0.0, 0.0, 1.0); + float luma_zero = LUMA_texOff(0.0).x; + + vec2 pp = CHROMA_pos * CHROMA_size - vec2(0.5); + vec2 fp = floor(pp); + pp -= fp; + + vec2 chroma_pixels[12]; + chroma_pixels[0] = CHROMA_tex(vec2((fp + vec2(0.5, -0.5)) * CHROMA_pt)).xy; + chroma_pixels[1] = CHROMA_tex(vec2((fp + vec2(1.5, -0.5)) * CHROMA_pt)).xy; + chroma_pixels[2] = CHROMA_tex(vec2((fp + vec2(-0.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[3] = CHROMA_tex(vec2((fp + vec2( 0.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[4] = CHROMA_tex(vec2((fp + vec2( 1.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[5] = CHROMA_tex(vec2((fp + vec2( 2.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[6] = CHROMA_tex(vec2((fp + vec2(-0.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[7] = CHROMA_tex(vec2((fp + vec2( 0.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[8] = CHROMA_tex(vec2((fp + vec2( 1.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[9] = CHROMA_tex(vec2((fp + vec2( 2.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[10] = CHROMA_tex(vec2((fp + vec2(0.5, 2.5) ) * CHROMA_pt)).xy; + chroma_pixels[11] = CHROMA_tex(vec2((fp + vec2(1.5, 2.5) ) * CHROMA_pt)).xy; + + float luma_pixels[12]; + luma_pixels[0] = LUMA_LOWRES_tex(vec2((fp + vec2(0.5, -0.5)) * CHROMA_pt)).x; + luma_pixels[1] = LUMA_LOWRES_tex(vec2((fp + vec2(1.5, -0.5)) * CHROMA_pt)).x; + luma_pixels[2] = LUMA_LOWRES_tex(vec2((fp + vec2(-0.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[3] = LUMA_LOWRES_tex(vec2((fp + vec2( 0.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[4] = LUMA_LOWRES_tex(vec2((fp + vec2( 1.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[5] = LUMA_LOWRES_tex(vec2((fp + vec2( 2.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[6] = LUMA_LOWRES_tex(vec2((fp + vec2(-0.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[7] = LUMA_LOWRES_tex(vec2((fp + vec2( 0.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[8] = LUMA_LOWRES_tex(vec2((fp + vec2( 1.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[9] = LUMA_LOWRES_tex(vec2((fp + vec2( 2.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[10] = LUMA_LOWRES_tex(vec2((fp + vec2(0.5, 2.5) ) * CHROMA_pt)).x; + luma_pixels[11] = LUMA_LOWRES_tex(vec2((fp + vec2(1.5, 2.5) ) * CHROMA_pt)).x; + + vec2 chroma_min = vec2(1e8); + chroma_min = min(chroma_min, chroma_pixels[3]); + chroma_min = min(chroma_min, chroma_pixels[4]); + chroma_min = min(chroma_min, chroma_pixels[7]); + chroma_min = min(chroma_min, chroma_pixels[8]); + + vec2 chroma_max = vec2(1e-8); + chroma_max = max(chroma_max, chroma_pixels[3]); + chroma_max = max(chroma_max, chroma_pixels[4]); + chroma_max = max(chroma_max, chroma_pixels[7]); + chroma_max = max(chroma_max, chroma_pixels[8]); + + float wd[12]; + wd[0] = comp_wd(vec2( 0.0,-1.0) - pp); + wd[1] = comp_wd(vec2( 1.0,-1.0) - pp); + wd[2] = comp_wd(vec2(-1.0, 0.0) - pp); + wd[3] = comp_wd(vec2( 0.0, 0.0) - pp); + wd[4] = comp_wd(vec2( 1.0, 0.0) - pp); + wd[5] = comp_wd(vec2( 2.0, 0.0) - pp); + wd[6] = comp_wd(vec2(-1.0, 1.0) - pp); + wd[7] = comp_wd(vec2( 0.0, 1.0) - pp); + wd[8] = comp_wd(vec2( 1.0, 1.0) - pp); + wd[9] = comp_wd(vec2( 2.0, 1.0) - pp); + wd[10] = comp_wd(vec2( 0.0, 2.0) - pp); + wd[11] = comp_wd(vec2( 1.0, 2.0) - pp); + + float wt = 0.0; + for (int i = 0; i < 12; i++) { + wt += wd[i]; + } + + vec2 ct = vec2(0.0); + for (int i = 0; i < 12; i++) { + ct += wd[i] * chroma_pixels[i]; + } + + vec2 chroma_spatial = ct / wt; + chroma_spatial = clamp(chroma_spatial, chroma_min, chroma_max); + + float luma_avg_4 = 0.0; + luma_avg_4 += luma_pixels[3]; + luma_avg_4 += luma_pixels[4]; + luma_avg_4 += luma_pixels[7]; + luma_avg_4 += luma_pixels[8]; + luma_avg_4 /= 4.0; + + float luma_var_4 = 0.0; + luma_var_4 += pow(luma_pixels[3] - luma_avg_4, 2.0); + luma_var_4 += pow(luma_pixels[4] - luma_avg_4, 2.0); + luma_var_4 += pow(luma_pixels[7] - luma_avg_4, 2.0); + luma_var_4 += pow(luma_pixels[8] - luma_avg_4, 2.0); + + vec2 chroma_avg_4 = vec2(0.0); + chroma_avg_4 += chroma_pixels[3]; + chroma_avg_4 += chroma_pixels[4]; + chroma_avg_4 += chroma_pixels[7]; + chroma_avg_4 += chroma_pixels[8]; + chroma_avg_4 /= 4.0; + + vec2 luma_chroma_cov_4 = vec2(0.0); + luma_chroma_cov_4 += (luma_pixels[3] - luma_avg_4) * (chroma_pixels[3] - chroma_avg_4); + luma_chroma_cov_4 += (luma_pixels[4] - luma_avg_4) * (chroma_pixels[4] - chroma_avg_4); + luma_chroma_cov_4 += (luma_pixels[7] - luma_avg_4) * (chroma_pixels[7] - chroma_avg_4); + luma_chroma_cov_4 += (luma_pixels[8] - luma_avg_4) * (chroma_pixels[8] - chroma_avg_4); + + vec2 alpha_4 = luma_chroma_cov_4 / max(luma_var_4, division_limit); + vec2 beta_4 = chroma_avg_4 - alpha_4 * luma_avg_4; + + vec2 chroma_pred_4 = alpha_4 * luma_zero + beta_4; + chroma_pred_4 = clamp(chroma_pred_4, 0.0, 1.0); + + float luma_avg_12 = 0.0; + for(int i = 0; i < 12; i++) { + luma_avg_12 += luma_pixels[i]; + } + luma_avg_12 /= 12.0; + + float luma_var_12 = 0.0; + for(int i = 0; i < 12; i++) { + luma_var_12 += pow(luma_pixels[i] - luma_avg_12, 2.0); + } + + vec2 chroma_avg_12 = vec2(0.0); + for(int i = 0; i < 12; i++) { + chroma_avg_12 += chroma_pixels[i]; + } + chroma_avg_12 /= 12.0; + + vec2 chroma_var_12 = vec2(0.0); + for(int i = 0; i < 12; i++) { + chroma_var_12 += pow(chroma_pixels[i] - chroma_avg_12, vec2(2.0)); + } + + vec2 luma_chroma_cov_12 = vec2(0.0); + for(int i = 0; i < 12; i++) { + luma_chroma_cov_12 += (luma_pixels[i] - luma_avg_12) * (chroma_pixels[i] - chroma_avg_12); + } + + vec2 corr = abs(luma_chroma_cov_12 / max(sqrt(luma_var_12 * chroma_var_12), division_limit)); + corr = clamp(corr, 0.0, 1.0); + + output_pix.xy = mix(chroma_spatial, chroma_pred_4, pow(corr, vec2(2.0)) / 2.0); + + // Replace this with chroma_min and chroma_max if you want AR + // output_pix.yz = clamp(output_pix.yz, chroma_min, chroma_max); + output_pix.xy = clamp(output_pix.xy, 0.0, 1.0); + return output_pix; +} \ No newline at end of file diff --git a/.config/mpv/shaders/CfL_Prediction_native.glsl b/.config/mpv/shaders/CfL_Prediction_native.glsl new file mode 100755 index 0000000..e654034 --- /dev/null +++ b/.config/mpv/shaders/CfL_Prediction_native.glsl @@ -0,0 +1,197 @@ +// MIT License + +// Copyright (c) 2023 João Chrisóstomo + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +//!HOOK CHROMA +//!BIND CHROMA +//!BIND LUMA +//!SAVE LUMA_LOWRES +//!WIDTH CHROMA.w +//!HEIGHT LUMA.h +//!WHEN CHROMA.w LUMA.w < +//!DESC Chroma From Luma Prediction (Downscaling Luma 1st Step) + +vec4 hook() { + float factor = ceil(LUMA_size.x / CHROMA_size.x); + int start = int(ceil(-factor - 0.5)); + int end = int(floor(factor - 0.5)); + float filter_end = float(end) + 1.5; + + float output_luma = 0.0; + float wt = 0.0; + for (int dx = start; dx <= end; dx++) { + float luma_pix = LUMA_texOff(vec2(dx + 0.5, 0.0)).x; + float wd = smoothstep(0.0, filter_end, filter_end - length(vec2(dx + 0.5, 0.0))); + output_luma += luma_pix * wd; + wt += wd; + } + vec4 output_pix = vec4(output_luma / wt, 0.0, 0.0, 1.0); + return output_pix; +} + +//!HOOK CHROMA +//!BIND CHROMA +//!BIND LUMA_LOWRES +//!SAVE LUMA_LOWRES +//!WIDTH CHROMA.w +//!HEIGHT CHROMA.h +//!WHEN CHROMA.w LUMA.w < +//!DESC Chroma From Luma Prediction (Downscaling Luma 2nd Step) + +vec4 hook() { + float factor = ceil(LUMA_LOWRES_size.y / CHROMA_size.y); + int start = int(ceil(-factor - 0.5)); + int end = int(floor(factor - 0.5)); + float filter_end = float(end) + 1.5; + + float output_luma = 0.0; + float wt = 0.0; + for (int dy = start; dy <= end; dy++) { + float luma_pix = LUMA_LOWRES_texOff(vec2(0.0, dy + 0.5)).x; + float wd = smoothstep(0.0, filter_end, filter_end - length(vec2(0.0, dy + 0.5))); + output_luma += luma_pix * wd; + wt += wd; + } + vec4 output_pix = vec4(output_luma / wt, 0.0, 0.0, 1.0); + return output_pix; +} + +//!HOOK NATIVE +//!BIND LUMA_LOWRES +//!BIND CHROMA +//!BIND NATIVE +//!OFFSET ALIGN +//!WHEN CHROMA.w LUMA.w < +//!DESC Chroma From Luma Prediction (Upscaling Chroma) + +vec4 hook() { + float division_limit = 1e-4; + + vec4 output_pix = NATIVE_texOff(0.0); + float luma_zero = output_pix.x; + + vec2 pp = CHROMA_pos * CHROMA_size - vec2(0.5); + vec2 fp = floor(pp); + pp -= fp; + + vec2 chroma_pixels[12]; + chroma_pixels[0] = CHROMA_tex(vec2((fp + vec2(0.5, -0.5)) * CHROMA_pt)).xy; + chroma_pixels[1] = CHROMA_tex(vec2((fp + vec2(1.5, -0.5)) * CHROMA_pt)).xy; + chroma_pixels[2] = CHROMA_tex(vec2((fp + vec2(-0.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[3] = CHROMA_tex(vec2((fp + vec2( 0.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[4] = CHROMA_tex(vec2((fp + vec2( 1.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[5] = CHROMA_tex(vec2((fp + vec2( 2.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[6] = CHROMA_tex(vec2((fp + vec2(-0.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[7] = CHROMA_tex(vec2((fp + vec2( 0.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[8] = CHROMA_tex(vec2((fp + vec2( 1.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[9] = CHROMA_tex(vec2((fp + vec2( 2.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[10] = CHROMA_tex(vec2((fp + vec2(0.5, 2.5) ) * CHROMA_pt)).xy; + chroma_pixels[11] = CHROMA_tex(vec2((fp + vec2(1.5, 2.5) ) * CHROMA_pt)).xy; + + float luma_pixels[12]; + luma_pixels[0] = LUMA_LOWRES_tex(vec2((fp + vec2(0.5, -0.5)) * CHROMA_pt)).x; + luma_pixels[1] = LUMA_LOWRES_tex(vec2((fp + vec2(1.5, -0.5)) * CHROMA_pt)).x; + luma_pixels[2] = LUMA_LOWRES_tex(vec2((fp + vec2(-0.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[3] = LUMA_LOWRES_tex(vec2((fp + vec2( 0.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[4] = LUMA_LOWRES_tex(vec2((fp + vec2( 1.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[5] = LUMA_LOWRES_tex(vec2((fp + vec2( 2.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[6] = LUMA_LOWRES_tex(vec2((fp + vec2(-0.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[7] = LUMA_LOWRES_tex(vec2((fp + vec2( 0.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[8] = LUMA_LOWRES_tex(vec2((fp + vec2( 1.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[9] = LUMA_LOWRES_tex(vec2((fp + vec2( 2.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[10] = LUMA_LOWRES_tex(vec2((fp + vec2(0.5, 2.5) ) * CHROMA_pt)).x; + luma_pixels[11] = LUMA_LOWRES_tex(vec2((fp + vec2(1.5, 2.5) ) * CHROMA_pt)).x; + + float luma_avg_4 = 0.0; + luma_avg_4 += luma_pixels[3]; + luma_avg_4 += luma_pixels[4]; + luma_avg_4 += luma_pixels[7]; + luma_avg_4 += luma_pixels[8]; + luma_avg_4 /= 4.0; + + float luma_var_4 = 0.0; + luma_var_4 += pow(luma_pixels[3] - luma_avg_4, 2.0); + luma_var_4 += pow(luma_pixels[4] - luma_avg_4, 2.0); + luma_var_4 += pow(luma_pixels[7] - luma_avg_4, 2.0); + luma_var_4 += pow(luma_pixels[8] - luma_avg_4, 2.0); + + vec2 chroma_avg_4 = vec2(0.0); + chroma_avg_4 += chroma_pixels[3]; + chroma_avg_4 += chroma_pixels[4]; + chroma_avg_4 += chroma_pixels[7]; + chroma_avg_4 += chroma_pixels[8]; + chroma_avg_4 /= 4.0; + + vec2 luma_chroma_cov_4 = vec2(0.0); + luma_chroma_cov_4 += (luma_pixels[3] - luma_avg_4) * (chroma_pixels[3] - chroma_avg_4); + luma_chroma_cov_4 += (luma_pixels[4] - luma_avg_4) * (chroma_pixels[4] - chroma_avg_4); + luma_chroma_cov_4 += (luma_pixels[7] - luma_avg_4) * (chroma_pixels[7] - chroma_avg_4); + luma_chroma_cov_4 += (luma_pixels[8] - luma_avg_4) * (chroma_pixels[8] - chroma_avg_4); + + vec2 alpha_4 = luma_chroma_cov_4 / max(luma_var_4, division_limit); + vec2 beta_4 = chroma_avg_4 - alpha_4 * luma_avg_4; + + vec2 chroma_pred_4 = alpha_4 * luma_zero + beta_4; + chroma_pred_4 = clamp(chroma_pred_4, 0.0, 1.0); + + float luma_avg_12 = 0.0; + for(int i = 0; i < 12; i++) { + luma_avg_12 += luma_pixels[i]; + } + luma_avg_12 /= 12.0; + + float luma_var_12 = 0.0; + for(int i = 0; i < 12; i++) { + luma_var_12 += pow(luma_pixels[i] - luma_avg_12, 2.0); + } + + vec2 chroma_avg_12 = vec2(0.0); + for(int i = 0; i < 12; i++) { + chroma_avg_12 += chroma_pixels[i]; + } + chroma_avg_12 /= 12.0; + + vec2 chroma_var_12 = vec2(0.0); + for(int i = 0; i < 12; i++) { + chroma_var_12 += pow(chroma_pixels[i] - chroma_avg_12, vec2(2.0)); + } + + vec2 luma_chroma_cov_12 = vec2(0.0); + for(int i = 0; i < 12; i++) { + luma_chroma_cov_12 += (luma_pixels[i] - luma_avg_12) * (chroma_pixels[i] - chroma_avg_12); + } + + vec2 corr = abs(luma_chroma_cov_12 / max(sqrt(luma_var_12 * chroma_var_12), division_limit)); + corr = clamp(corr, 0.0, 1.0); + + vec2 alpha_12 = luma_chroma_cov_12 / max(luma_var_12, division_limit); + vec2 beta_12 = chroma_avg_12 - alpha_12 * luma_avg_12; + + vec2 chroma_pred_12 = alpha_12 * luma_zero + beta_12; + chroma_pred_12 = clamp(chroma_pred_12, 0.0, 1.0); + + chroma_pred_4 = mix(output_pix.yz, chroma_pred_4, pow(corr, vec2(2.0)) / 2.0); + chroma_pred_12 = mix(output_pix.yz, chroma_pred_12, pow(corr, vec2(2.0)) / 2.0); + output_pix.yz = mix(chroma_pred_4, chroma_pred_12, 0.5); + + output_pix.yz = clamp(output_pix.yz, 0.0, 1.0); + return output_pix; +} \ No newline at end of file diff --git a/.config/mpv/shaders/FastBilateral.glsl b/.config/mpv/shaders/FastBilateral.glsl new file mode 100755 index 0000000..5b0becc --- /dev/null +++ b/.config/mpv/shaders/FastBilateral.glsl @@ -0,0 +1,79 @@ +// MIT License + +// Copyright (c) 2023 João Chrisóstomo + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +//!PARAM intensity_coeff +//!TYPE float +//!MINIMUM 0.0 +256.0 + +//!HOOK CHROMA +//!BIND CHROMA +//!BIND LUMA +//!WIDTH LUMA.w +//!HEIGHT LUMA.h +//!WHEN CHROMA.w LUMA.w < +//!OFFSET ALIGN +//!DESC Fast Bilateral (Upscaling Chroma) + +float comp_wi(float distance) { + return exp(-intensity_coeff * distance * distance); +} + +vec4 hook() { + vec2 pp = CHROMA_pos * CHROMA_size - vec2(0.5); + vec2 fp = floor(pp); + pp -= fp; + + float luma_00 = LUMA_texOff(0).x; + + vec2 chroma_11 = CHROMA_tex(vec2(fp + vec2(0.5)) * CHROMA_pt).xy; + vec2 chroma_12 = CHROMA_tex(vec2(fp + vec2(0.5, 1.5)) * CHROMA_pt).xy; + vec2 chroma_21 = CHROMA_tex(vec2(fp + vec2(1.5, 0.5)) * CHROMA_pt).xy; + vec2 chroma_22 = CHROMA_tex(vec2(fp + vec2(1.5, 1.5)) * CHROMA_pt).xy; + + float luma_11 = LUMA_tex(vec2(fp + vec2(0.5)) * CHROMA_pt).x; + float luma_12 = LUMA_tex(vec2(fp + vec2(0.5, 1.5)) * CHROMA_pt).x; + float luma_21 = LUMA_tex(vec2(fp + vec2(1.5, 0.5)) * CHROMA_pt).x; + float luma_22 = LUMA_tex(vec2(fp + vec2(1.5, 1.5)) * CHROMA_pt).x; + + float wd11 = (1 - pp.y) * (1 - pp.x); + float wd12 = pp.y * (1 - pp.x); + float wd21 = (1 - pp.y) * pp.x; + float wd22 = pp.y * pp.x; + + float wi11 = comp_wi(abs(luma_00 - luma_11)); + float wi12 = comp_wi(abs(luma_00 - luma_12)); + float wi21 = comp_wi(abs(luma_00 - luma_21)); + float wi22 = comp_wi(abs(luma_00 - luma_22)); + + float w11 = wd11 * wi11; + float w12 = wd12 * wi12; + float w21 = wd21 * wi21; + float w22 = wd22 * wi22; + + vec2 ct = chroma_11 * w11 + chroma_12 * w12 + chroma_21 * w21 + chroma_22 * w22; + float wt = w11 + w12 + w21 + w22; + + vec4 output_pix = vec4(0.0, 0.0, 0.0, 1.0); + output_pix.xy = ct / wt; + return output_pix; +} \ No newline at end of file diff --git a/.config/mpv/shaders/JointBilateral.glsl b/.config/mpv/shaders/JointBilateral.glsl new file mode 100755 index 0000000..68272a4 --- /dev/null +++ b/.config/mpv/shaders/JointBilateral.glsl @@ -0,0 +1,193 @@ +// MIT License + +// Copyright (c) 2023 João Chrisóstomo + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +//!HOOK CHROMA +//!BIND LUMA +//!BIND HOOKED +//!SAVE LUMA_LOWRES +//!WHEN CHROMA.w LUMA.w < +//!DESC Joint Bilateral (Downscaling Luma) + +vec4 hook() { + vec2 start = ceil((LUMA_pos - CHROMA_pt) * LUMA_size - 0.5); + vec2 end = floor((LUMA_pos + CHROMA_pt) * LUMA_size - 0.5); + + float luma_pix = 0.0; + float w = 0.0; + float d = 0.0; + float wt = 0.0; + float val = 0.0; + vec2 pos = LUMA_pos; + + for (float dx = start.x; dx <= end.x; dx++) { + for (float dy = start.y; dy <= end.y; dy++) { + pos = LUMA_pt * vec2(dx + 0.5, dy + 0.5); + d = length((pos - LUMA_pos) * CHROMA_size); + w = exp(-2.0 * pow(d, 2.0)); + luma_pix = LUMA_tex(pos).x; + val += w * luma_pix; + wt += w; + } + } + + vec4 output_pix = vec4(val / wt, 0.0, 0.0, 1.0); + return output_pix; +} + +//!PARAM distance_coeff +//!TYPE float +//!MINIMUM 0.0 +4.0 + +//!PARAM intensity_coeff +//!TYPE float +//!MINIMUM 0.0 +256.0 + +//!HOOK CHROMA +//!BIND CHROMA +//!BIND LUMA +//!BIND LUMA_LOWRES +//!WIDTH LUMA.w +//!HEIGHT LUMA.h +//!WHEN CHROMA.w LUMA.w < +//!OFFSET ALIGN +//!DESC Joint Bilateral (Upscaling Chroma) + +float comp_wd(vec2 distance) { + return exp(-distance_coeff * (distance.x * distance.x + distance.y * distance.y)); +} + +float comp_wi(float distance) { + return exp(-intensity_coeff * distance * distance); +} + +float comp_w(float wd, float wi) { + float w = wd * wi; + // return clamp(w, 1e-32, 1.0); + return w; +} + +vec4 hook() { + vec2 pp = CHROMA_pos * CHROMA_size - vec2(0.5); + vec2 fp = floor(pp); + pp -= fp; + + vec2 chroma_b = CHROMA_tex(vec2((fp + vec2(0.5, -0.5)) * CHROMA_pt)).xy; + vec2 chroma_c = CHROMA_tex(vec2((fp + vec2(1.5, -0.5)) * CHROMA_pt)).xy; + vec2 chroma_e = CHROMA_tex(vec2((fp + vec2(-0.5, 0.5)) * CHROMA_pt)).xy; + vec2 chroma_f = CHROMA_tex(vec2((fp + vec2( 0.5, 0.5)) * CHROMA_pt)).xy; + vec2 chroma_g = CHROMA_tex(vec2((fp + vec2( 1.5, 0.5)) * CHROMA_pt)).xy; + vec2 chroma_h = CHROMA_tex(vec2((fp + vec2( 2.5, 0.5)) * CHROMA_pt)).xy; + vec2 chroma_i = CHROMA_tex(vec2((fp + vec2(-0.5, 1.5)) * CHROMA_pt)).xy; + vec2 chroma_j = CHROMA_tex(vec2((fp + vec2( 0.5, 1.5)) * CHROMA_pt)).xy; + vec2 chroma_k = CHROMA_tex(vec2((fp + vec2( 1.5, 1.5)) * CHROMA_pt)).xy; + vec2 chroma_l = CHROMA_tex(vec2((fp + vec2( 2.5, 1.5)) * CHROMA_pt)).xy; + vec2 chroma_n = CHROMA_tex(vec2((fp + vec2(0.5, 2.5) ) * CHROMA_pt)).xy; + vec2 chroma_o = CHROMA_tex(vec2((fp + vec2(1.5, 2.5) ) * CHROMA_pt)).xy; + + float luma_0 = LUMA_texOff(0.0).x; + float luma_b = LUMA_LOWRES_tex(vec2((fp + vec2(0.5, -0.5)) * CHROMA_pt)).x; + float luma_c = LUMA_LOWRES_tex(vec2((fp + vec2(1.5, -0.5)) * CHROMA_pt)).x; + float luma_e = LUMA_LOWRES_tex(vec2((fp + vec2(-0.5, 0.5)) * CHROMA_pt)).x; + float luma_f = LUMA_LOWRES_tex(vec2((fp + vec2( 0.5, 0.5)) * CHROMA_pt)).x; + float luma_g = LUMA_LOWRES_tex(vec2((fp + vec2( 1.5, 0.5)) * CHROMA_pt)).x; + float luma_h = LUMA_LOWRES_tex(vec2((fp + vec2( 2.5, 0.5)) * CHROMA_pt)).x; + float luma_i = LUMA_LOWRES_tex(vec2((fp + vec2(-0.5, 1.5)) * CHROMA_pt)).x; + float luma_j = LUMA_LOWRES_tex(vec2((fp + vec2( 0.5, 1.5)) * CHROMA_pt)).x; + float luma_k = LUMA_LOWRES_tex(vec2((fp + vec2( 1.5, 1.5)) * CHROMA_pt)).x; + float luma_l = LUMA_LOWRES_tex(vec2((fp + vec2( 2.5, 1.5)) * CHROMA_pt)).x; + float luma_n = LUMA_LOWRES_tex(vec2((fp + vec2(0.5, 2.5) ) * CHROMA_pt)).x; + float luma_o = LUMA_LOWRES_tex(vec2((fp + vec2(1.5, 2.5) ) * CHROMA_pt)).x; + + float wd_b = comp_wd(vec2( 0.0,-1.0) - pp); + float wd_c = comp_wd(vec2( 1.0,-1.0) - pp); + float wd_e = comp_wd(vec2(-1.0, 0.0) - pp); + float wd_f = comp_wd(vec2( 0.0, 0.0) - pp); + float wd_g = comp_wd(vec2( 1.0, 0.0) - pp); + float wd_h = comp_wd(vec2( 2.0, 0.0) - pp); + float wd_i = comp_wd(vec2(-1.0, 1.0) - pp); + float wd_j = comp_wd(vec2( 0.0, 1.0) - pp); + float wd_k = comp_wd(vec2( 1.0, 1.0) - pp); + float wd_l = comp_wd(vec2( 2.0, 1.0) - pp); + float wd_n = comp_wd(vec2( 0.0, 2.0) - pp); + float wd_o = comp_wd(vec2( 1.0, 2.0) - pp); + + float wi_b = comp_wi(luma_0 - luma_b); + float wi_c = comp_wi(luma_0 - luma_c); + float wi_e = comp_wi(luma_0 - luma_e); + float wi_f = comp_wi(luma_0 - luma_f); + float wi_g = comp_wi(luma_0 - luma_g); + float wi_h = comp_wi(luma_0 - luma_h); + float wi_i = comp_wi(luma_0 - luma_i); + float wi_j = comp_wi(luma_0 - luma_j); + float wi_k = comp_wi(luma_0 - luma_k); + float wi_l = comp_wi(luma_0 - luma_l); + float wi_n = comp_wi(luma_0 - luma_n); + float wi_o = comp_wi(luma_0 - luma_o); + + float w_b = comp_w(wd_b, wi_b); + float w_c = comp_w(wd_c, wi_c); + float w_e = comp_w(wd_e, wi_e); + float w_f = comp_w(wd_f, wi_f); + float w_g = comp_w(wd_g, wi_g); + float w_h = comp_w(wd_h, wi_h); + float w_i = comp_w(wd_i, wi_i); + float w_j = comp_w(wd_j, wi_j); + float w_k = comp_w(wd_k, wi_k); + float w_l = comp_w(wd_l, wi_l); + float w_n = comp_w(wd_n, wi_n); + float w_o = comp_w(wd_o, wi_o); + + float wt = 0.0; + wt += w_b; + wt += w_c; + wt += w_e; + wt += w_f; + wt += w_g; + wt += w_h; + wt += w_i; + wt += w_j; + wt += w_k; + wt += w_l; + wt += w_n; + wt += w_o; + + vec2 ct = vec2(0.0); + ct += w_b * chroma_b; + ct += w_c * chroma_c; + ct += w_e * chroma_e; + ct += w_f * chroma_f; + ct += w_g * chroma_g; + ct += w_h * chroma_h; + ct += w_i * chroma_i; + ct += w_j * chroma_j; + ct += w_k * chroma_k; + ct += w_l * chroma_l; + ct += w_n * chroma_n; + ct += w_o * chroma_o; + + vec4 output_pix = vec4(0.0, 0.0, 0.0, 1.0); + output_pix.xy = ct / wt; + output_pix.xy = clamp(output_pix.xy, 0.0, 1.0); + return output_pix; +} diff --git a/.config/mpv/shaders/KrigBilateral.glsl b/.config/mpv/shaders/KrigBilateral.glsl new file mode 100755 index 0000000..681f098 --- /dev/null +++ b/.config/mpv/shaders/KrigBilateral.glsl @@ -0,0 +1,214 @@ +// KrigBilateral by Shiandow +// +// 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 CHROMA +//!BIND LUMA +//!BIND HOOKED +//!SAVE LOWRES_Y +//!WIDTH LUMA.w +//!WHEN CHROMA.w LUMA.w < +//!DESC KrigBilateral Downscaling Y pass 1 + +#define offset vec2(0) + +#define axis 1 + +#define Kernel(x) dot(vec3(0.42659, -0.49656, 0.076849), cos(vec3(0, 1, 2) * acos(-1.) * (x + 1.))) + +vec4 hook() { + // Calculate bounds + float low = ceil((LUMA_pos - CHROMA_pt) * LUMA_size - offset - 0.5)[axis]; + float high = floor((LUMA_pos + CHROMA_pt) * LUMA_size - offset - 0.5)[axis]; + + float W = 0.0; + vec4 avg = vec4(0); + vec2 pos = LUMA_pos; + + for (float k = low; k <= high; k++) { + pos[axis] = LUMA_pt[axis] * (k - offset[axis] + 0.5); + float rel = (pos[axis] - LUMA_pos[axis])*CHROMA_size[axis]; + float w = Kernel(rel); + + vec4 y = textureGrad(LUMA_raw, pos, vec2(0.0), vec2(0.0)).xxxx * LUMA_mul; + y.y *= y.y; + avg += w * y; + W += w; + } + avg /= W; + avg.y = abs(avg.y - avg.x * avg.x); + return avg; +} + +//!HOOK CHROMA +//!BIND LOWRES_Y +//!BIND HOOKED +//!SAVE LOWRES_Y +//!WHEN CHROMA.w LUMA.w < +//!DESC KrigBilateral Downscaling Y pass 2 + +#define offset vec2(0) + +#define axis 0 + +#define Kernel(x) dot(vec3(0.42659, -0.49656, 0.076849), cos(vec3(0, 1, 2) * acos(-1.) * (x + 1.))) + +vec4 hook() { + // Calculate bounds + float low = ceil((LOWRES_Y_pos - CHROMA_pt) * LOWRES_Y_size - offset - 0.5)[axis]; + float high = floor((LOWRES_Y_pos + CHROMA_pt) * LOWRES_Y_size - offset - 0.5)[axis]; + + float W = 0.0; + vec4 avg = vec4(0); + vec2 pos = LOWRES_Y_pos; + + for (float k = low; k <= high; k++) { + pos[axis] = LOWRES_Y_pt[axis] * (k - offset[axis] + 0.5); + float rel = (pos[axis] - LOWRES_Y_pos[axis])*CHROMA_size[axis]; + float w = Kernel(rel); + + vec4 y = textureGrad(LOWRES_Y_raw, pos, vec2(0.0), vec2(0.0)).xxxx * LOWRES_Y_mul; + y.y *= y.y; + avg += w * y; + W += w; + } + avg /= W; + avg.y = abs(avg.y - avg.x * avg.x) + LOWRES_Y_texOff(0).y; + return avg; +} + +//!HOOK CHROMA +//!BIND HOOKED +//!BIND LUMA +//!BIND LOWRES_Y +//!WIDTH LUMA.w +//!HEIGHT LUMA.h +//!WHEN CHROMA.w LUMA.w < +//!OFFSET ALIGN +//!DESC KrigBilateral Upscaling UV + +#define sqr(x) dot(x,x) +#define sigma_nsq 256.0/(255.0*255.0) + +#define N 8 + +#define M(i,j) Mx[min(i,j)*N + max(i,j) - (min(i,j)*(min(i,j)+1))/2] + +#define C(i,j) (inversesqrt(1.0 + (X[i].y + X[j].y) / Var) * exp(-0.5 * (sqr(X[i].x - X[j].x) / (localVar + X[i].y + X[j].y) + sqr((coords[i] - coords[j]) / radius))) /*+ (X[i].x - y) * (X[j].x - y) / Var*/) // commented out part works well only on test patterns +#define c(i) (inversesqrt(1.0 + X[i].y / Var) * exp(-0.5 * (sqr(X[i].x - y) / (localVar + X[i].y) + sqr((coords[i] - offset) / radius)))) + +#define getnsum(i) X[i] = vec4(LOWRES_Y_tex(LOWRES_Y_pt*(pos+coords[i]+vec2(0.5))).xy, \ + CHROMA_tex(CHROMA_pt*(pos+coords[i]+vec2(0.5))).xy); \ + w = clamp(1.5 - abs(coords[i]), 0.0, 1.0); \ + total += w.x*w.y*vec4(X[i].x, X[i].x * X[i].x, X[i].y, 1.0); + +#define I3(f, n) f(n) f(n+1) f(n+2) +#define I9(f, n) I3(f, n) I3(f, n+3) I3(f, n+6) + +vec4 hook() { + vec2 pos = CHROMA_pos * HOOKED_size - vec2(0.5); + vec2 offset = pos - round(pos); + pos -= offset; + + vec2 coords[N+1]; + vec4 X[N+1]; + vec2 w; + vec4 total = vec4(0); + + coords[0] = vec2(-1,-1); coords[1] = vec2(-1, 0); coords[2] = vec2(-1, 1); + coords[3] = vec2( 0,-1); coords[4] = vec2( 0, 1); coords[5] = vec2( 1,-1); + coords[6] = vec2( 1, 0); coords[7] = vec2( 1, 1); coords[8] = vec2( 0, 0); + + I9(getnsum, 0) + + total.xyz /= total.w; + float localVar = abs(total.y - total.x * total.x) + sigma_nsq; + float Var = localVar + total.z; + float radius = 1.0; + + float y = LUMA_texOff(0).x; + float Mx[(N*(N+1))/2]; + float b[N]; + vec2 interp = X[N].zw; + + b[0] = c(0) - c(N) - C(0,N) + C(N,N); M(0, 0) = C(0,0) - C(0,N) - C(0,N) + C(N,N); M(0, 1) = C(0,1) - C(1,N) - C(0,N) + C(N,N); M(0, 2) = C(0,2) - C(2,N) - C(0,N) + C(N,N); M(0, 3) = C(0,3) - C(3,N) - C(0,N) + C(N,N); M(0, 4) = C(0,4) - C(4,N) - C(0,N) + C(N,N); M(0, 5) = C(0,5) - C(5,N) - C(0,N) + C(N,N); M(0, 6) = C(0,6) - C(6,N) - C(0,N) + C(N,N); M(0, 7) = C(0,7) - C(7,N) - C(0,N) + C(N,N); + b[1] = c(1) - c(N) - C(1,N) + C(N,N); M(1, 1) = C(1,1) - C(1,N) - C(1,N) + C(N,N); M(1, 2) = C(1,2) - C(2,N) - C(1,N) + C(N,N); M(1, 3) = C(1,3) - C(3,N) - C(1,N) + C(N,N); M(1, 4) = C(1,4) - C(4,N) - C(1,N) + C(N,N); M(1, 5) = C(1,5) - C(5,N) - C(1,N) + C(N,N); M(1, 6) = C(1,6) - C(6,N) - C(1,N) + C(N,N); M(1, 7) = C(1,7) - C(7,N) - C(1,N) + C(N,N); + b[2] = c(2) - c(N) - C(2,N) + C(N,N); M(2, 2) = C(2,2) - C(2,N) - C(2,N) + C(N,N); M(2, 3) = C(2,3) - C(3,N) - C(2,N) + C(N,N); M(2, 4) = C(2,4) - C(4,N) - C(2,N) + C(N,N); M(2, 5) = C(2,5) - C(5,N) - C(2,N) + C(N,N); M(2, 6) = C(2,6) - C(6,N) - C(2,N) + C(N,N); M(2, 7) = C(2,7) - C(7,N) - C(2,N) + C(N,N); + b[3] = c(3) - c(N) - C(3,N) + C(N,N); M(3, 3) = C(3,3) - C(3,N) - C(3,N) + C(N,N); M(3, 4) = C(3,4) - C(4,N) - C(3,N) + C(N,N); M(3, 5) = C(3,5) - C(5,N) - C(3,N) + C(N,N); M(3, 6) = C(3,6) - C(6,N) - C(3,N) + C(N,N); M(3, 7) = C(3,7) - C(7,N) - C(3,N) + C(N,N); + b[4] = c(4) - c(N) - C(4,N) + C(N,N); M(4, 4) = C(4,4) - C(4,N) - C(4,N) + C(N,N); M(4, 5) = C(4,5) - C(5,N) - C(4,N) + C(N,N); M(4, 6) = C(4,6) - C(6,N) - C(4,N) + C(N,N); M(4, 7) = C(4,7) - C(7,N) - C(4,N) + C(N,N); + b[5] = c(5) - c(N) - C(5,N) + C(N,N); M(5, 5) = C(5,5) - C(5,N) - C(5,N) + C(N,N); M(5, 6) = C(5,6) - C(6,N) - C(5,N) + C(N,N); M(5, 7) = C(5,7) - C(7,N) - C(5,N) + C(N,N); + b[6] = c(6) - c(N) - C(6,N) + C(N,N); M(6, 6) = C(6,6) - C(6,N) - C(6,N) + C(N,N); M(6, 7) = C(6,7) - C(7,N) - C(6,N) + C(N,N); + b[7] = c(7) - c(N) - C(7,N) + C(N,N); M(7, 7) = C(7,7) - C(7,N) - C(7,N) + C(N,N); + + b[1] -= b[0] * M(0, 1) / M(0, 0); M(1, 1) -= M(0, 1) * M(0, 1) / M(0, 0); M(1, 2) -= M(0, 2) * M(0, 1) / M(0, 0); M(1, 3) -= M(0, 3) * M(0, 1) / M(0, 0); M(1, 4) -= M(0, 4) * M(0, 1) / M(0, 0); M(1, 5) -= M(0, 5) * M(0, 1) / M(0, 0); M(1, 6) -= M(0, 6) * M(0, 1) / M(0, 0); M(1, 7) -= M(0, 7) * M(0, 1) / M(0, 0); + b[2] -= b[0] * M(0, 2) / M(0, 0); M(2, 2) -= M(0, 2) * M(0, 2) / M(0, 0); M(2, 3) -= M(0, 3) * M(0, 2) / M(0, 0); M(2, 4) -= M(0, 4) * M(0, 2) / M(0, 0); M(2, 5) -= M(0, 5) * M(0, 2) / M(0, 0); M(2, 6) -= M(0, 6) * M(0, 2) / M(0, 0); M(2, 7) -= M(0, 7) * M(0, 2) / M(0, 0); + b[3] -= b[0] * M(0, 3) / M(0, 0); M(3, 3) -= M(0, 3) * M(0, 3) / M(0, 0); M(3, 4) -= M(0, 4) * M(0, 3) / M(0, 0); M(3, 5) -= M(0, 5) * M(0, 3) / M(0, 0); M(3, 6) -= M(0, 6) * M(0, 3) / M(0, 0); M(3, 7) -= M(0, 7) * M(0, 3) / M(0, 0); + b[4] -= b[0] * M(0, 4) / M(0, 0); M(4, 4) -= M(0, 4) * M(0, 4) / M(0, 0); M(4, 5) -= M(0, 5) * M(0, 4) / M(0, 0); M(4, 6) -= M(0, 6) * M(0, 4) / M(0, 0); M(4, 7) -= M(0, 7) * M(0, 4) / M(0, 0); + b[5] -= b[0] * M(0, 5) / M(0, 0); M(5, 5) -= M(0, 5) * M(0, 5) / M(0, 0); M(5, 6) -= M(0, 6) * M(0, 5) / M(0, 0); M(5, 7) -= M(0, 7) * M(0, 5) / M(0, 0); + b[6] -= b[0] * M(0, 6) / M(0, 0); M(6, 6) -= M(0, 6) * M(0, 6) / M(0, 0); M(6, 7) -= M(0, 7) * M(0, 6) / M(0, 0); + b[7] -= b[0] * M(0, 7) / M(0, 0); M(7, 7) -= M(0, 7) * M(0, 7) / M(0, 0); + + b[2] -= b[1] * M(1, 2) / M(1, 1); M(2, 2) -= M(1, 2) * M(1, 2) / M(1, 1); M(2, 3) -= M(1, 3) * M(1, 2) / M(1, 1); M(2, 4) -= M(1, 4) * M(1, 2) / M(1, 1); M(2, 5) -= M(1, 5) * M(1, 2) / M(1, 1); M(2, 6) -= M(1, 6) * M(1, 2) / M(1, 1); M(2, 7) -= M(1, 7) * M(1, 2) / M(1, 1); + b[3] -= b[1] * M(1, 3) / M(1, 1); M(3, 3) -= M(1, 3) * M(1, 3) / M(1, 1); M(3, 4) -= M(1, 4) * M(1, 3) / M(1, 1); M(3, 5) -= M(1, 5) * M(1, 3) / M(1, 1); M(3, 6) -= M(1, 6) * M(1, 3) / M(1, 1); M(3, 7) -= M(1, 7) * M(1, 3) / M(1, 1); + b[4] -= b[1] * M(1, 4) / M(1, 1); M(4, 4) -= M(1, 4) * M(1, 4) / M(1, 1); M(4, 5) -= M(1, 5) * M(1, 4) / M(1, 1); M(4, 6) -= M(1, 6) * M(1, 4) / M(1, 1); M(4, 7) -= M(1, 7) * M(1, 4) / M(1, 1); + b[5] -= b[1] * M(1, 5) / M(1, 1); M(5, 5) -= M(1, 5) * M(1, 5) / M(1, 1); M(5, 6) -= M(1, 6) * M(1, 5) / M(1, 1); M(5, 7) -= M(1, 7) * M(1, 5) / M(1, 1); + b[6] -= b[1] * M(1, 6) / M(1, 1); M(6, 6) -= M(1, 6) * M(1, 6) / M(1, 1); M(6, 7) -= M(1, 7) * M(1, 6) / M(1, 1); + b[7] -= b[1] * M(1, 7) / M(1, 1); M(7, 7) -= M(1, 7) * M(1, 7) / M(1, 1); + + b[3] -= b[2] * M(2, 3) / M(2, 2); M(3, 3) -= M(2, 3) * M(2, 3) / M(2, 2); M(3, 4) -= M(2, 4) * M(2, 3) / M(2, 2); M(3, 5) -= M(2, 5) * M(2, 3) / M(2, 2); M(3, 6) -= M(2, 6) * M(2, 3) / M(2, 2); M(3, 7) -= M(2, 7) * M(2, 3) / M(2, 2); + b[4] -= b[2] * M(2, 4) / M(2, 2); M(4, 4) -= M(2, 4) * M(2, 4) / M(2, 2); M(4, 5) -= M(2, 5) * M(2, 4) / M(2, 2); M(4, 6) -= M(2, 6) * M(2, 4) / M(2, 2); M(4, 7) -= M(2, 7) * M(2, 4) / M(2, 2); + b[5] -= b[2] * M(2, 5) / M(2, 2); M(5, 5) -= M(2, 5) * M(2, 5) / M(2, 2); M(5, 6) -= M(2, 6) * M(2, 5) / M(2, 2); M(5, 7) -= M(2, 7) * M(2, 5) / M(2, 2); + b[6] -= b[2] * M(2, 6) / M(2, 2); M(6, 6) -= M(2, 6) * M(2, 6) / M(2, 2); M(6, 7) -= M(2, 7) * M(2, 6) / M(2, 2); + b[7] -= b[2] * M(2, 7) / M(2, 2); M(7, 7) -= M(2, 7) * M(2, 7) / M(2, 2); + + b[4] -= b[3] * M(3, 4) / M(3, 3); M(4, 4) -= M(3, 4) * M(3, 4) / M(3, 3); M(4, 5) -= M(3, 5) * M(3, 4) / M(3, 3); M(4, 6) -= M(3, 6) * M(3, 4) / M(3, 3); M(4, 7) -= M(3, 7) * M(3, 4) / M(3, 3); + b[5] -= b[3] * M(3, 5) / M(3, 3); M(5, 5) -= M(3, 5) * M(3, 5) / M(3, 3); M(5, 6) -= M(3, 6) * M(3, 5) / M(3, 3); M(5, 7) -= M(3, 7) * M(3, 5) / M(3, 3); + b[6] -= b[3] * M(3, 6) / M(3, 3); M(6, 6) -= M(3, 6) * M(3, 6) / M(3, 3); M(6, 7) -= M(3, 7) * M(3, 6) / M(3, 3); + b[7] -= b[3] * M(3, 7) / M(3, 3); M(7, 7) -= M(3, 7) * M(3, 7) / M(3, 3); + + b[5] -= b[4] * M(4, 5) / M(4, 4); M(5, 5) -= M(4, 5) * M(4, 5) / M(4, 4); M(5, 6) -= M(4, 6) * M(4, 5) / M(4, 4); M(5, 7) -= M(4, 7) * M(4, 5) / M(4, 4); + b[6] -= b[4] * M(4, 6) / M(4, 4); M(6, 6) -= M(4, 6) * M(4, 6) / M(4, 4); M(6, 7) -= M(4, 7) * M(4, 6) / M(4, 4); + b[7] -= b[4] * M(4, 7) / M(4, 4); M(7, 7) -= M(4, 7) * M(4, 7) / M(4, 4); + + b[6] -= b[5] * M(5, 6) / M(5, 5); M(6, 6) -= M(5, 6) * M(5, 6) / M(5, 5); M(6, 7) -= M(5, 7) * M(5, 6) / M(5, 5); + b[7] -= b[5] * M(5, 7) / M(5, 5); M(7, 7) -= M(5, 7) * M(5, 7) / M(5, 5); + + b[7] -= b[6] * M(6, 7) / M(6, 6); M(7, 7) -= M(6, 7) * M(6, 7) / M(6, 6); + + b[7] /= M(7, 7); + interp += b[7] * (X[7] - X[N]).zw; + + b[6] -= M(6, 7) * b[7]; b[6] /= M(6, 6); + interp += b[6] * (X[6] - X[N]).zw; + + b[5] -= M(5, 6) * b[6]; b[5] -= M(5, 7) * b[7]; b[5] /= M(5, 5); + interp += b[5] * (X[5] - X[N]).zw; + + b[4] -= M(4, 5) * b[5]; b[4] -= M(4, 6) * b[6]; b[4] -= M(4, 7) * b[7]; b[4] /= M(4, 4); + interp += b[4] * (X[4] - X[N]).zw; + + b[3] -= M(3, 4) * b[4]; b[3] -= M(3, 5) * b[5]; b[3] -= M(3, 6) * b[6]; b[3] -= M(3, 7) * b[7]; b[3] /= M(3, 3); + interp += b[3] * (X[3] - X[N]).zw; + + b[2] -= M(2, 3) * b[3]; b[2] -= M(2, 4) * b[4]; b[2] -= M(2, 5) * b[5]; b[2] -= M(2, 6) * b[6]; b[2] -= M(2, 7) * b[7]; b[2] /= M(2, 2); + interp += b[2] * (X[2] - X[N]).zw; + + b[1] -= M(1, 2) * b[2]; b[1] -= M(1, 3) * b[3]; b[1] -= M(1, 4) * b[4]; b[1] -= M(1, 5) * b[5]; b[1] -= M(1, 6) * b[6]; b[1] -= M(1, 7) * b[7]; b[1] /= M(1, 1); + interp += b[1] * (X[1] - X[N]).zw; + + b[0] -= M(0, 1) * b[1]; b[0] -= M(0, 2) * b[2]; b[0] -= M(0, 3) * b[3]; b[0] -= M(0, 4) * b[4]; b[0] -= M(0, 5) * b[5]; b[0] -= M(0, 6) * b[6]; b[0] -= M(0, 7) * b[7]; b[0] /= M(0, 0); + interp += b[0] * (X[0] - X[N]).zw; + + return interp.xyxy; +} diff --git a/.config/mpv/shaders/MemeBilateral.glsl b/.config/mpv/shaders/MemeBilateral.glsl new file mode 100755 index 0000000..18e11ea --- /dev/null +++ b/.config/mpv/shaders/MemeBilateral.glsl @@ -0,0 +1,202 @@ +// MIT License + +// Copyright (c) 2023 João Chrisóstomo + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +//!PARAM distance_coeff +//!TYPE float +//!MINIMUM 0.0 +0.5 + +//!PARAM intensity_coeff +//!TYPE float +//!MINIMUM 0.0 +512.0 + +//!HOOK CHROMA +//!BIND CHROMA +//!BIND LUMA +//!WIDTH LUMA.w +//!HEIGHT LUMA.h +//!WHEN CHROMA.w LUMA.w < +//!OFFSET ALIGN +//!DESC Meme Bilateral (Upscaling Chroma) + +float comp_wd1(vec2 distance) { + float d = min(length(distance), 2.0); + if (d < 1.0) { + return (6.0 + d * d * (-15.0 + d * 9.0)) / 6.0; + } else { + return (12.0 + d * (-24.0 + d * (15.0 + d * -3.0))) / 6.0; + } +} + +float comp_wd2(vec2 distance) { + return exp(-distance_coeff * pow(length(distance), 2.0)); +} + +float comp_wi(float distance) { + return exp(-intensity_coeff * pow(distance, 2.0)); +} + +float comp_w(float wd, float wi) { + float w = wd * wi; + // return clamp(w, 1e-32, 1.0); + return w; +} + +vec4 hook() { + float division_limit = 1e-4; + float luma_zero = LUMA_texOff(0.0).x; + vec4 output_pix = vec4(0.0, 0.0, 0.0, 1.0); + + vec2 pp = CHROMA_pos * CHROMA_size - vec2(0.5); + vec2 fp = floor(pp); + pp -= fp; + + vec2 chroma_pixels[12]; + chroma_pixels[0] = CHROMA_tex(vec2((fp + vec2(0.5, -0.5)) * CHROMA_pt)).xy; + chroma_pixels[1] = CHROMA_tex(vec2((fp + vec2(1.5, -0.5)) * CHROMA_pt)).xy; + chroma_pixels[2] = CHROMA_tex(vec2((fp + vec2(-0.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[3] = CHROMA_tex(vec2((fp + vec2( 0.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[4] = CHROMA_tex(vec2((fp + vec2( 1.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[5] = CHROMA_tex(vec2((fp + vec2( 2.5, 0.5)) * CHROMA_pt)).xy; + chroma_pixels[6] = CHROMA_tex(vec2((fp + vec2(-0.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[7] = CHROMA_tex(vec2((fp + vec2( 0.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[8] = CHROMA_tex(vec2((fp + vec2( 1.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[9] = CHROMA_tex(vec2((fp + vec2( 2.5, 1.5)) * CHROMA_pt)).xy; + chroma_pixels[10] = CHROMA_tex(vec2((fp + vec2(0.5, 2.5) ) * CHROMA_pt)).xy; + chroma_pixels[11] = CHROMA_tex(vec2((fp + vec2(1.5, 2.5) ) * CHROMA_pt)).xy; + + float luma_pixels[12]; + luma_pixels[0] = LUMA_tex(vec2((fp + vec2(0.5, -0.5)) * CHROMA_pt)).x; + luma_pixels[1] = LUMA_tex(vec2((fp + vec2(1.5, -0.5)) * CHROMA_pt)).x; + luma_pixels[2] = LUMA_tex(vec2((fp + vec2(-0.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[3] = LUMA_tex(vec2((fp + vec2( 0.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[4] = LUMA_tex(vec2((fp + vec2( 1.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[5] = LUMA_tex(vec2((fp + vec2( 2.5, 0.5)) * CHROMA_pt)).x; + luma_pixels[6] = LUMA_tex(vec2((fp + vec2(-0.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[7] = LUMA_tex(vec2((fp + vec2( 0.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[8] = LUMA_tex(vec2((fp + vec2( 1.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[9] = LUMA_tex(vec2((fp + vec2( 2.5, 1.5)) * CHROMA_pt)).x; + luma_pixels[10] = LUMA_tex(vec2((fp + vec2(0.5, 2.5) ) * CHROMA_pt)).x; + luma_pixels[11] = LUMA_tex(vec2((fp + vec2(1.5, 2.5) ) * CHROMA_pt)).x; + + +// Sharp spatial filter + float wd1[12]; + wd1[0] = comp_wd1(vec2( 0.0,-1.0) - pp); + wd1[1] = comp_wd1(vec2( 1.0,-1.0) - pp); + wd1[2] = comp_wd1(vec2(-1.0, 0.0) - pp); + wd1[3] = comp_wd1(vec2( 0.0, 0.0) - pp); + wd1[4] = comp_wd1(vec2( 1.0, 0.0) - pp); + wd1[5] = comp_wd1(vec2( 2.0, 0.0) - pp); + wd1[6] = comp_wd1(vec2(-1.0, 1.0) - pp); + wd1[7] = comp_wd1(vec2( 0.0, 1.0) - pp); + wd1[8] = comp_wd1(vec2( 1.0, 1.0) - pp); + wd1[9] = comp_wd1(vec2( 2.0, 1.0) - pp); + wd1[10] = comp_wd1(vec2( 0.0, 2.0) - pp); + wd1[11] = comp_wd1(vec2( 1.0, 2.0) - pp); + + float wt1 = 0.0; + for (int i = 0; i < 12; i++) { + wt1 += wd1[i]; + } + + vec2 ct1 = vec2(0.0); + for (int i = 0; i < 12; i++) { + ct1 += wd1[i] * chroma_pixels[i]; + } + + vec2 chroma_spatial = ct1 / wt1; + +// Bilateral filter + float wd2[12]; + wd2[0] = comp_wd2(vec2( 0.0,-1.0) - pp); + wd2[1] = comp_wd2(vec2( 1.0,-1.0) - pp); + wd2[2] = comp_wd2(vec2(-1.0, 0.0) - pp); + wd2[3] = comp_wd2(vec2( 0.0, 0.0) - pp); + wd2[4] = comp_wd2(vec2( 1.0, 0.0) - pp); + wd2[5] = comp_wd2(vec2( 2.0, 0.0) - pp); + wd2[6] = comp_wd2(vec2(-1.0, 1.0) - pp); + wd2[7] = comp_wd2(vec2( 0.0, 1.0) - pp); + wd2[8] = comp_wd2(vec2( 1.0, 1.0) - pp); + wd2[9] = comp_wd2(vec2( 2.0, 1.0) - pp); + wd2[10] = comp_wd2(vec2( 0.0, 2.0) - pp); + wd2[11] = comp_wd2(vec2( 1.0, 2.0) - pp); + + float wi[12]; + for (int i = 0; i < 12; i++) { + wi[i] = comp_wi(luma_zero - luma_pixels[i]); + } + + float w[12]; + for (int i = 0; i < 12; i++) { + w[i] = comp_w(wd2[i], wi[i]); + } + + float wt2 = 0.0; + for (int i = 0; i < 12; i++) { + wt2 += w[i]; + } + + vec2 ct2 = vec2(0.0); + for (int i = 0; i < 12; i++) { + ct2 += w[i] * chroma_pixels[i]; + } + + vec2 chroma_bilat = ct2 / wt2; + + +// Coefficient of determination + float luma_avg_12 = 0.0; + for(int i = 0; i < 12; i++) { + luma_avg_12 += luma_pixels[i]; + } + luma_avg_12 /= 12.0; + + float luma_var_12 = 0.0; + for(int i = 0; i < 12; i++) { + luma_var_12 += pow(luma_pixels[i] - luma_avg_12, 2.0); + } + + vec2 chroma_avg_12 = vec2(0.0); + for(int i = 0; i < 12; i++) { + chroma_avg_12 += chroma_pixels[i]; + } + chroma_avg_12 /= 12.0; + + vec2 chroma_var_12 = vec2(0.0); + for(int i = 0; i < 12; i++) { + chroma_var_12 += pow(chroma_pixels[i] - chroma_avg_12, vec2(2.0)); + } + + vec2 luma_chroma_cov_12 = vec2(0.0); + for(int i = 0; i < 12; i++) { + luma_chroma_cov_12 += (luma_pixels[i] - luma_avg_12) * (chroma_pixels[i] - chroma_avg_12); + } + + vec2 corr = abs(luma_chroma_cov_12 / max(sqrt(luma_var_12 * chroma_var_12), division_limit)); + corr = clamp(corr, 0.0, 1.0); + + output_pix.xy = mix(chroma_spatial, chroma_bilat, pow(corr, vec2(2.0)) / 2.0); + output_pix.xy = clamp(output_pix.xy, 0.0, 1.0); + return output_pix; +}