// 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 HOOKED //!BIND LUMA //!SAVE LOWRES_Y //!WIDTH LUMA.w //!WHEN CHROMA.w LUMA.w < //!DESC KrigBilateral Downscaling Y pass 1 #define offset vec2(0,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 - pow(avg.x, 2.0)); return avg; } //!HOOK CHROMA //!BIND HOOKED //!BIND LOWRES_Y //!SAVE LOWRES_Y //!WHEN CHROMA.w LUMA.w < //!DESC KrigBilateral Downscaling Y pass 2 #define offset vec2(0,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 - pow(avg.x, 2.0)) + 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 // -- Convenience -- #define sqr(x) dot(x,x) #define bitnoise 1.0/(2.0*255.0) #define noise 0.05//5.0*bitnoise #define chromaOffset vec2(0.0, 0.0) // -- Window Size -- #define taps 3 #define even (float(taps) - 2.0 * floor(float(taps) / 2.0) == 0.0) #define minX int(1.0-ceil(float(taps)/2.0)) #define maxX int(floor(float(taps)/2.0)) #define Kernel(x) (cos(acos(-1.0)*(x)/float(taps))) // Hann kernel // -- Input processing -- #define GetY(coord) LOWRES_Y_tex(LOWRES_Y_pt*(pos+coord+vec2(0.5))).xy #define GetUV(coord) CHROMA_tex(CHROMA_pt*(pos+coord+vec2(0.5))).xy #define N (taps*taps - 1) #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)/localVar) * 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) / localVar) #define c(i) (inversesqrt(1.0 + X[i].y/localVar) * exp(-0.5*(sqr(X[i].x - y)/(localVar + X[i].y) + sqr((coords[i] - offset)/radius)))) vec4 hook() { vec2 pos = CHROMA_pos * HOOKED_size - chromaOffset - vec2(0.5); vec2 offset = pos - (even ? floor(pos) : round(pos)); pos -= offset; vec2 coords[N+1]; vec4 X[N+1]; float y = LUMA_texOff(0).x; 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); for (int i=0; i