// SSimDownscaler 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 POSTKERNEL //!BIND HOOKED //!BIND PREKERNEL //!SAVE L2 //!HEIGHT NATIVE_CROPPED.h //!WHEN NATIVE_CROPPED.w POSTKERNEL.w > //!COMPONENTS 3 //!DESC SSimDownscaler calc L2 pass 1 #define factor ((input_size*POSTKERNEL_pt)[axis]) #define axis 0 #define offset vec2(0,0) #define MN(B,C,x) (x <= 1.0 ? ((2.-1.5*B-C)*x + (-3.+2.*B+C))*x*x + (1.-B/3.) : (((-B/6.-C)*x + (B+5.*C))*x + (-2.*B-8.*C))*x+((4./3.)*B+4.*C)) #define Kernel(x) MN(1.0/3.0, 1.0/3.0, abs(x)) #define taps 2.0 vec4 hook() { vec2 base = PREKERNEL_pt * (PREKERNEL_pos * input_size + tex_offset); // Calculate bounds float low = floor((PREKERNEL_pos - taps*POSTKERNEL_pt) * input_size - offset + tex_offset + 0.5)[axis]; float high = floor((PREKERNEL_pos + taps*POSTKERNEL_pt) * input_size - offset + tex_offset + 0.5)[axis]; float W = 0.0; vec4 avg = vec4(0); vec2 pos = base; for (float k = 0.0; k < high - low; k++) { pos[axis] = PREKERNEL_pt[axis] * (k + low + 0.5); float rel = (pos[axis] - base[axis])*POSTKERNEL_size[axis] + offset[axis]*factor; float w = Kernel(rel); avg += w * pow(clamp(textureLod(PREKERNEL_raw, pos, 0.0) * PREKERNEL_mul, 0.0, 1.0), vec4(2.0)); W += w; } avg /= W; return avg; } //!HOOK POSTKERNEL //!BIND HOOKED //!BIND L2 //!SAVE L2 //!WHEN NATIVE_CROPPED.h POSTKERNEL.h > //!COMPONENTS 3 //!DESC SSimDownscaler calc L2 pass 2 #define factor ((L2_size*POSTKERNEL_pt)[axis]) #define axis 1 #define offset vec2(0,0) #define MN(B,C,x) (x <= 1.0 ? ((2.-1.5*B-C)*x + (-3.+2.*B+C))*x*x + (1.-B/3.) : (((-B/6.-C)*x + (B+5.*C))*x + (-2.*B-8.*C))*x+((4./3.)*B+4.*C)) #define Kernel(x) MN(1.0/3.0, 1.0/3.0, abs(x)) #define taps 2.0 vec4 hook() { // Calculate bounds float low = floor((L2_pos - taps*POSTKERNEL_pt) * L2_size - offset + 0.5)[axis]; float high = floor((L2_pos + taps*POSTKERNEL_pt) * L2_size - offset + 0.5)[axis]; float W = 0.0; vec4 avg = vec4(0); vec2 pos = L2_pos; for (float k = 0.0; k < high - low; k++) { pos[axis] = L2_pt[axis] * (k + low + 0.5); float rel = (pos[axis] - L2_pos[axis])*POSTKERNEL_size[axis] + offset[axis]*factor; float w = Kernel(rel); avg += w * textureLod(L2_raw, pos, 0.0) * L2_mul; W += w; } avg /= W; return avg; } //!HOOK POSTKERNEL //!BIND HOOKED //!SAVE M //!WHEN NATIVE_CROPPED.w POSTKERNEL.w > //!COMPONENTS 3 //!DESC SSimDownscaler calc Mean #define locality 8.0 #define offset vec2(0,0) #define Kernel(x) pow(1.0 / locality, abs(x)) #define taps 3.0 #define maxtaps taps vec4 ScaleH(vec2 pos) { // Calculate bounds float low = floor(-0.5*maxtaps - offset)[0]; float high = floor(+0.5*maxtaps - offset)[0]; float W = 0.0; vec4 avg = vec4(0); for (float k = 0.0; k < maxtaps; k++) { pos[0] = POSTKERNEL_pos[0] + POSTKERNEL_pt[0] * (k + low + 1.0); float rel = (k + low + 1.0) + offset[0]; float w = Kernel(rel); avg += w * clamp(POSTKERNEL_tex(pos), 0.0, 1.0); W += w; } avg /= W; return avg; } vec4 hook() { // Calculate bounds float low = floor(-0.5*maxtaps - offset)[1]; float high = floor(+0.5*maxtaps - offset)[1]; float W = 0.0; vec4 avg = vec4(0); vec2 pos = POSTKERNEL_pos; for (float k = 0.0; k < maxtaps; k++) { pos[1] = POSTKERNEL_pos[1] + POSTKERNEL_pt[1] * (k + low + 1.0); float rel = (k + low + 1.0) + offset[1]; float w = Kernel(rel); avg += w * ScaleH(pos); W += w; } avg /= W; return avg; } //!HOOK POSTKERNEL //!BIND HOOKED //!BIND L2 //!BIND M //!SAVE R //!WHEN NATIVE_CROPPED.w POSTKERNEL.w > //!COMPONENTS 3 //!DESC SSimDownscaler calc R #define locality 8.0 #define offset vec2(0,0) #define Kernel(x) pow(1.0 / locality, abs(x)) #define taps 3.0 #define maxtaps taps mat2x4 ScaleH(vec2 pos) { // Calculate bounds float low = floor(-0.5*maxtaps - offset)[0]; float high = floor(+0.5*maxtaps - offset)[0]; float W = 0.0; mat2x4 avg = mat2x4(0); for (float k = 0.0; k < maxtaps; k++) { pos[0] = L2_pos[0] + L2_pt[0] * (k + low + 1.0); float rel = (k + low + 1.0) + offset[0]; float w = Kernel(rel); avg += w * mat2x4(pow(clamp(POSTKERNEL_tex(pos), 0.0, 1.0), vec4(2.0)), L2_tex(pos)); W += w; } avg /= W; return avg; } vec4 hook() { // Calculate bounds float low = floor(-0.5*maxtaps - offset)[1]; float high = floor(+0.5*maxtaps - offset)[1]; float W = 0.0; mat2x4 avg = mat2x4(0); vec2 pos = L2_pos; for (float k = 0.0; k < maxtaps; k++) { pos[1] = L2_pos[1] + L2_pt[1] * (k + low + 1.0); float rel = (k + low + 1.0) + offset[1]; float w = Kernel(rel); avg += w * ScaleH(pos); W += w; } avg /= W; vec3 Sl = abs(avg[0].rgb - pow(M_texOff(0).rgb, vec3(2.0))); vec3 Sh = abs(avg[1].rgb - pow(M_texOff(0).rgb, vec3(2.0))); return vec4(mix(vec3(0.5), 1.0 / (1.0 + sqrt(Sh / Sl)), lessThan(vec3(5e-6), Sl)), 0.0); } //!HOOK POSTKERNEL //!BIND HOOKED //!BIND M //!BIND R //!WHEN NATIVE_CROPPED.w POSTKERNEL.w > //!DESC SSimDownscaler final pass #define locality 8.0 #define offset vec2(0,0) #define Kernel(x) pow(1.0 / locality, abs(x)) #define taps 3.0 #define maxtaps taps #define Gamma(x) ( pow(x, vec3(1.0/2.0)) ) #define GammaInv(x) ( pow(clamp(x, 0.0, 1.0), vec3(2.0)) ) mat3x3 ScaleH(vec2 pos) { // Calculate bounds float low = floor(-0.5*maxtaps - offset)[0]; float high = floor(+0.5*maxtaps - offset)[0]; float W = 0.0; mat3x3 avg = mat3x3(0); for (float k = 0.0; k < maxtaps; k++) { pos[0] = POSTKERNEL_pos[0] + POSTKERNEL_pt[0] * (k + low + 1.0); float rel = (k + low + 1.0) + offset[0]; float w = Kernel(rel); vec3 M = Gamma(M_tex(pos).rgb); vec3 R = R_tex(pos).rgb; R = 1.0 / R - 1.0; avg += w * mat3x3(R*M, M, R); W += w; } avg /= W; return avg; } vec4 hook() { // Calculate bounds float low = floor(-0.5*maxtaps - offset)[1]; float high = floor(+0.5*maxtaps - offset)[1]; float W = 0.0; mat3x3 avg = mat3x3(0); vec2 pos = POSTKERNEL_pos; for (float k = 0.0; k < maxtaps; k++) { pos[1] = POSTKERNEL_pos[1] + POSTKERNEL_pt[1] * (k + low + 1.0); float rel = (k + low + 1.0) + offset[1]; float w = Kernel(rel); avg += w * ScaleH(pos); W += w; } avg /= W; vec4 L = clamp(POSTKERNEL_texOff(0), 0.0, 1.0); return vec4(GammaInv(avg[1] + avg[2] * Gamma(L.rgb) - avg[0]), L.w); }