updated mpv config

This commit is contained in:
gaitas13 2023-10-14 22:16:26 +02:00
parent 84a165c7b8
commit f6b7bc94ef
10 changed files with 1669 additions and 21 deletions

View file

@ -1 +1 @@
d script-message cycle-profiles "bwdifdeint;deinterlace-no"
#d script-message cycle-profiles "bwdifdeint;deinterlace-no"

View file

@ -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=<filter>
#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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}