Update main xBR shaders

- New color distance function to improve IQ;
- Merge noblend and aa shaders in same files;
- Better param descriptions;
- New param to switch between noblend and aa;
- New lv1, lv2-multipass and lv3-9x.
This commit is contained in:
Hyllian 2022-07-16 07:50:47 -03:00
parent 6b0413b1fe
commit b57ea11402
10 changed files with 1333 additions and 312 deletions

View file

@ -0,0 +1,138 @@
#version 450
/*
Copyright (C) 2010 Team XBMC
http://www.xbmc.org
Copyright (C) 2011 Stefanos A.
http://www.opentk.com
This Program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This Program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with XBMC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
http://www.gnu.org/copyleft/gpl.html
*/
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
float B, C;
} params;
// Default to Mitchel-Netravali coefficients for best psychovisual result
// bicubic-sharp is B = 0.1 and C = 0.5
// bicubic-sharper is B = 0.0 and C = 0.75
// Hyllian: using params for B-Spline (B=1.0, C=0.0). Very good at getting rid of jaggies.
#pragma parameter B "Bicubic Coeff B" 1.00 0.0 1.0 0.01
#pragma parameter C "Bicubic Coeff C" 0.00 0.0 1.0 0.01
#define B params.B
#define C params.C
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
} global;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
float weight(float x)
{
float ax = abs(x);
if (ax < 1.0)
{
return
(
pow(x, 2.0) * ((12.0 - 9.0 * B - 6.0 * C) * ax + (-18.0 + 12.0 * B + 6.0 * C)) +
(6.0 - 2.0 * B)
) / 6.0;
}
else if ((ax >= 1.0) && (ax < 2.0))
{
return
(
pow(x, 2.0) * ((-B - 6.0 * C) * ax + (6.0 * B + 30.0 * C)) +
(-12.0 * B - 48.0 * C) * ax + (8.0 * B + 24.0 * C)
) / 6.0;
}
else
{
return 0.0;
}
}
vec4 weight4(float x)
{
return vec4(
weight(x - 2.0),
weight(x - 1.0),
weight(x),
weight(x + 1.0));
}
vec3 pixel(float xpos, float ypos, sampler2D tex)
{
return texture(tex, vec2(xpos, ypos)).rgb;
}
vec3 line_run(float ypos, vec4 xpos, vec4 linetaps, sampler2D tex)
{
return
pixel(xpos.r, ypos, tex) * linetaps.r +
pixel(xpos.g, ypos, tex) * linetaps.g +
pixel(xpos.b, ypos, tex) * linetaps.b +
pixel(xpos.a, ypos, tex) * linetaps.a;
}
void main()
{
vec2 stepxy = vec2(1.0/params.SourceSize.x, 1.0/params.SourceSize.y);
vec2 pos = vTexCoord.xy + stepxy * 0.5;
vec2 f = fract(pos / stepxy);
vec4 linetaps = weight4(1.0 - f.x);
vec4 columntaps = weight4(1.0 - f.y);
//make sure all taps added together is exactly 1.0, otherwise some (very small) distortion can occur
linetaps /= linetaps.r + linetaps.g + linetaps.b + linetaps.a;
columntaps /= columntaps.r + columntaps.g + columntaps.b + columntaps.a;
vec2 xystart = (-1.5 - f) * stepxy + pos;
vec4 xpos = vec4(xystart.x, xystart.x + stepxy.x, xystart.x + stepxy.x * 2.0, xystart.x + stepxy.x * 3.0);
// final sum and weight normalization
vec4 final = vec4(line_run(xystart.y , xpos, linetaps, Source) * columntaps.r +
line_run(xystart.y + stepxy.y , xpos, linetaps, Source) * columntaps.g +
line_run(xystart.y + stepxy.y * 2.0, xpos, linetaps, Source) * columntaps.b +
line_run(xystart.y + stepxy.y * 3.0, xpos, linetaps, Source) * columntaps.a,1);
FragColor = final;
}

281
xbr/shaders/xbr-lv1.slang Normal file
View file

@ -0,0 +1,281 @@
#version 450
/*
Hyllian's xBR-lv1 Shader
Copyright (C) 2011-2022 Hyllian - sergiogdb@gmail.com
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.
Incorporates some of the ideas from SABR shader. Thanks to Joshua Street.
*/
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
float XBR_EQ_THRESHOLD;
float XBR_BLENDING;
} params;
#pragma parameter XBR_EQ_THRESHOLD "COLOR DISTINCTION THRESHOLD" 0.32 0.0 1.0 0.01
#pragma parameter XBR_BLENDING "BLENDING [ NOBLEND | AA ]" 1.0 0.0 1.0 1.0
#define XBR_EQ_THRESHOLD params.XBR_EQ_THRESHOLD
#define XBR_BLENDING params.XBR_BLENDING
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
} global;
// Uncomment just one of the three params below to choose the corner detection
//#define CORNER_A
//#define CORNER_B
#define CORNER_C
#define saturate(c) clamp(c, 0.0, 1.0)
const vec4 Ao = vec4( 1.0, -1.0, -1.0, 1.0 );
const vec4 Bo = vec4( 1.0, 1.0, -1.0,-1.0 );
const vec4 Co = vec4( 1.5, 0.5, -0.5, 0.5 );
const vec4 Ci = vec4(0.25, 0.25, 0.25, 0.25);
const vec3 v2f = vec3( 65536, 256, 1); // vec to float encode
const vec3 Y = vec3(0.2627, 0.6780, 0.0593);
// Return if A components are less than or equal B ones.
vec4 LTE(vec4 A, vec4 B)
{
return step(A, B);
}
// Return if A components are less than B ones.
vec4 LT(vec4 A, vec4 B)
{
return vec4(lessThan(A, B));
}
// Return logically inverted vector components. BEWARE: Only works with 0.0 or 1.0 components.
vec4 NOT(vec4 A)
{
return (vec4(1.0) - A);
}
// Compare two vectors and return their components are different.
vec4 diff(vec4 A, vec4 B)
{
return vec4(notEqual(A, B));
}
float dist(vec3 A, vec3 B)
{
return dot(abs(A-B), Y);
}
// Calculate color distance between two vectors of four pixels
vec4 dist4(mat4x3 A, mat4x3 B)
{
return vec4(dist(A[0],B[0]), dist(A[1],B[1]), dist(A[2],B[2]), dist(A[3],B[3]));
}
// Tests if color components are under a threshold. In this case they are considered 'equal'.
vec4 eq(mat4x3 A, mat4x3 B)
{
return (step(dist4(A, B), vec4(XBR_EQ_THRESHOLD)));
}
// Determine if two vector components are NOT equal based on a threshold.
vec4 neq(mat4x3 A, mat4x3 B)
{
return (vec4(1.0, 1.0, 1.0, 1.0) - eq(A, B));
}
// Calculate weighted distance among pixels in some directions.
vec4 weighted_distance(mat4x3 a, mat4x3 b, mat4x3 c, mat4x3 d, mat4x3 e, mat4x3 f, mat4x3 g, mat4x3 h)
{
return (dist4(a,b) + dist4(a,c) + dist4(d,e) + dist4(d,f) + 4.0*dist4(g,h));
}
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 texCoord;
layout(location = 1) out vec4 t1;
layout(location = 2) out vec4 t2;
layout(location = 3) out vec4 t3;
layout(location = 4) out vec4 t4;
layout(location = 5) out vec4 t5;
layout(location = 6) out vec4 t6;
layout(location = 7) out vec4 t7;
layout(location = 8) out float aa_factor;
void main()
{
gl_Position = global.MVP * Position;
texCoord = TexCoord * 1.0001;
aa_factor = 2.0*params.OutputSize.z * params.SourceSize.x;
float dx = params.SourceSize.z;
float dy = params.SourceSize.w;
// A1 B1 C1
// A0 A B C C4
// D0 D E F F4
// G0 G H I I4
// G5 H5 I5
t1 = texCoord.xxxy + vec4( -dx, 0, dx,-2.0*dy); // A1 B1 C1
t2 = texCoord.xxxy + vec4( -dx, 0, dx, -dy); // A B C
t3 = texCoord.xxxy + vec4( -dx, 0, dx, 0); // D E F
t4 = texCoord.xxxy + vec4( -dx, 0, dx, dy); // G H I
t5 = texCoord.xxxy + vec4( -dx, 0, dx, 2.0*dy); // G5 H5 I5
t6 = texCoord.xyyy + vec4(-2.0*dx,-dy, 0, dy); // A0 D0 G0
t7 = texCoord.xyyy + vec4( 2.0*dx,-dy, 0, dy); // C4 F4 I4
}
#pragma stage fragment
layout(location = 0) in vec2 texCoord;
layout(location = 1) in vec4 t1;
layout(location = 2) in vec4 t2;
layout(location = 3) in vec4 t3;
layout(location = 4) in vec4 t4;
layout(location = 5) in vec4 t5;
layout(location = 6) in vec4 t6;
layout(location = 7) in vec4 t7;
layout(location = 8) in float aa_factor;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
void main()
{
vec4 edri, edr, px; // px = pixel, edr = edge detection rule
vec4 irlv0, irlv1;
vec4 fx; // inequations of straight lines.
vec3 res1, res2;
vec4 fx45i, fx45;
vec2 fp = fract(texCoord*params.SourceSize.xy);
vec3 A1 = texture(Source, t1.xw ).xyz;
vec3 B1 = texture(Source, t1.yw ).xyz;
vec3 C1 = texture(Source, t1.zw ).xyz;
vec3 A = texture(Source, t2.xw ).xyz;
vec3 B = texture(Source, t2.yw ).xyz;
vec3 C = texture(Source, t2.zw ).xyz;
vec3 D = texture(Source, t3.xw ).xyz;
vec3 E = texture(Source, t3.yw ).xyz;
vec3 F = texture(Source, t3.zw ).xyz;
vec3 G = texture(Source, t4.xw ).xyz;
vec3 H = texture(Source, t4.yw ).xyz;
vec3 I = texture(Source, t4.zw ).xyz;
vec3 G5 = texture(Source, t5.xw ).xyz;
vec3 H5 = texture(Source, t5.yw ).xyz;
vec3 I5 = texture(Source, t5.zw ).xyz;
vec3 A0 = texture(Source, t6.xy ).xyz;
vec3 D0 = texture(Source, t6.xz ).xyz;
vec3 G0 = texture(Source, t6.xw ).xyz;
vec3 C4 = texture(Source, t7.xy ).xyz;
vec3 F4 = texture(Source, t7.xz ).xyz;
vec3 I4 = texture(Source, t7.xw ).xyz;
mat4x3 b = mat4x3(B, D, H, F);
mat4x3 c = mat4x3(C, A, G, I);
mat4x3 d = mat4x3(D, H, F, B);
mat4x3 e = mat4x3(E, E, E, E);
mat4x3 f = mat4x3(F, B, D, H);
mat4x3 g = mat4x3(G, I, C, A);
mat4x3 h = mat4x3(H, F, B, D);
mat4x3 i = mat4x3(I, C, A, G);
mat4x3 i4 = mat4x3(I4, C1, A0, G5);
mat4x3 i5 = mat4x3(I5, C4, A1, G0);
mat4x3 h5 = mat4x3(H5, F4, B1, D0);
mat4x3 f4 = mat4x3(F4, B1, D0, H5);
vec4 b_ = v2f * b;
vec4 c_ = v2f * c;
vec4 d_ = b_.yzwx;
vec4 e_ = v2f * e;
vec4 f_ = b_.wxyz;
vec4 g_ = c_.zwxy;
vec4 h_ = b_.zwxy;
vec4 i_ = c_.wxyz;
vec4 i4_ = v2f * i4;
vec4 i5_ = v2f * i5;
vec4 h5_ = v2f * h5;
vec4 f4_ = h5_.yzwx;
// These inequations define the line below which interpolation occurs.
fx = ( Ao*fp.y + Bo*fp.x );
irlv0 = diff(e_,f_) * diff(e_,h_);
irlv1 = irlv0;
#ifdef CORNER_B
irlv1 = saturate(irlv0 * ( neq(f,b) * neq(h,d) + eq(e,i) * neq(f,i4) * neq(h,i5) + eq(e,g) + eq(e,c) ) );
#endif
#ifdef CORNER_C
irlv1 = saturate(irlv0 * ( neq(f,b) * neq(f,c) + neq(h,d) * neq(h,g) + eq(e,i) * (neq(f,f4) * neq(f,i4) + neq(h,h5) * neq(h,i5)) + eq(e,g) + eq(e,c)) );
#endif
if (XBR_BLENDING == 1.0) {
vec4 delta = vec4(aa_factor);
fx45i = saturate( 0.5 + (fx - Co - Ci) / delta );
fx45 = saturate( 0.5 + (fx - Co ) / delta );
}
else {
fx45i = LT( Co + Ci, fx );
fx45 = LT( Co, fx );
}
vec4 wd1 = weighted_distance( e, c, g, i, h5, f4, h, f);
vec4 wd2 = weighted_distance( h, d, i5, f, i4, b, e, i);
edri = LTE(wd1, wd2) * irlv0;
edr = LT( wd1, wd2) * irlv1 * NOT(edri.yzwx * edri.wxyz);
fx45i = edri * fx45i;
fx45 = edr * fx45;
px = LTE(dist4(e,f), dist4(e,h));
vec4 maximos = max(fx45, fx45i);
res1 = mix(E, mix(H, F, px.x), maximos.x);
res2 = mix(E, mix(B, D, px.z), maximos.z);
vec3 res1a = mix(res1, res2, step(dist(E, res1), dist(E, res2)));
res1 = mix(E, mix(F, B, px.y), maximos.y);
res2 = mix(E, mix(D, H, px.w), maximos.w);
vec3 res1b = mix(res1, res2, step(dist(E, res1), dist(E, res2)));
vec3 res = mix(res1a, res1b, step(dist(E, res1a), dist(E, res1b)));
FragColor = vec4(res, 1.0);
}

View file

@ -0,0 +1,261 @@
#version 450
/*
Hyllian's xBR-lv2 - pass0 Shader
Copyright (C) 2011-2022 Hyllian - sergiogdb@gmail.com
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.
Incorporates some of the ideas from SABR shader. Thanks to Joshua Street.
*/
layout(push_constant) uniform Push
{
float XBR_EQ_THRESHOLD;
float XBR_LV2_COEFFICIENT;
} params;
#pragma parameter XBR_EQ_THRESHOLD "COLOR DISTINCTION THRESHOLD" 0.32 0.0 1.0 0.01
#pragma parameter XBR_LV2_COEFFICIENT "SMOOTHNESS THRESHOLD" 0.3 0.0 1.0 0.1
#define XBR_EQ_THRESHOLD params.XBR_EQ_THRESHOLD
#define XBR_LV2_COEFFICIENT params.XBR_LV2_COEFFICIENT
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
} global;
// Uncomment just one of the three params below to choose the corner detection
//#define CORNER_A
//#define CORNER_B
#define CORNER_C
#define lv2_cf (XBR_LV2_COEFFICIENT + 2.0)
#define saturate(c) clamp(c, 0.0, 1.0)
#define round(X) floor((X)+0.5)
const vec3 v2f = vec3( 65536, 256, 1); // vec to float encode
const vec4 zip = vec4( 1.0, 2.0, 4.0, 8.0);
const vec4 low = vec4( 0.0, 0.0, 0.0, 0.0);
const vec4 high = vec4(255.0, 255.0, 255.0, 255.0);
const vec3 Y = vec3(0.2627, 0.6780, 0.0593);
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
layout(location = 1) out vec4 t1;
layout(location = 2) out vec4 t2;
layout(location = 3) out vec4 t3;
layout(location = 4) out vec4 t4;
layout(location = 5) out vec4 t5;
layout(location = 6) out vec4 t6;
layout(location = 7) out vec4 t7;
void main()
{
gl_Position = global.MVP * Position;
// vTexCoord = TexCoord;
vTexCoord = TexCoord * 1.0001;
float dx = global.SourceSize.z;
float dy = global.SourceSize.w;
// A1 B1 C1
// A0 A B C C4
// D0 D E F F4
// G0 G H I I4
// G5 H5 I5
t1 = vTexCoord.xxxy + vec4( -dx, 0, dx,-2.0*dy); // A1 B1 C1
t2 = vTexCoord.xxxy + vec4( -dx, 0, dx, -dy); // A B C
t3 = vTexCoord.xxxy + vec4( -dx, 0, dx, 0); // D E F
t4 = vTexCoord.xxxy + vec4( -dx, 0, dx, dy); // G H I
t5 = vTexCoord.xxxy + vec4( -dx, 0, dx, 2.0*dy); // G5 H5 I5
t6 = vTexCoord.xyyy + vec4(-2.0*dx,-dy, 0, dy); // A0 D0 G0
t7 = vTexCoord.xyyy + vec4( 2.0*dx,-dy, 0, dy); // C4 F4 I4
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 1) in vec4 t1;
layout(location = 2) in vec4 t2;
layout(location = 3) in vec4 t3;
layout(location = 4) in vec4 t4;
layout(location = 5) in vec4 t5;
layout(location = 6) in vec4 t6;
layout(location = 7) in vec4 t7;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
vec4 remapTo01(vec4 v, vec4 low, vec4 high)
{
return saturate((v - low)/(high-low));
}
// Return if A components are less than or equal B ones.
vec4 LTE(vec4 A, vec4 B)
{
return step(A, B);
}
// Return if A components are less than B ones.
vec4 LT(vec4 A, vec4 B)
{
return vec4(lessThan(A, B));
}
// Return logically inverted vector components. BEWARE: Only works with 0.0 or 1.0 components.
vec4 NOT(vec4 A)
{
return (vec4(1.0) - A);
}
// Compare two vectors and return their components are different.
vec4 diff(vec4 A, vec4 B)
{
return vec4(notEqual(A, B));
}
float dist(vec3 A, vec3 B)
{
return dot(abs(A-B), Y);
}
// Calculate color distance between two vectors of four pixels
vec4 dist4(mat4x3 A, mat4x3 B)
{
return vec4(dist(A[0],B[0]), dist(A[1],B[1]), dist(A[2],B[2]), dist(A[3],B[3]));
}
// Tests if color components are under a threshold. In this case they are considered 'equal'.
vec4 eq(mat4x3 A, mat4x3 B)
{
return (step(dist4(A, B), vec4(XBR_EQ_THRESHOLD)));
}
// Determine if two vector components are NOT equal based on a threshold.
vec4 neq(mat4x3 A, mat4x3 B)
{
return (vec4(1.0, 1.0, 1.0, 1.0) - eq(A, B));
}
// Calculate weighted distance among pixels in some directions.
vec4 weighted_distance(mat4x3 a, mat4x3 b, mat4x3 c, mat4x3 d, mat4x3 e, mat4x3 f, mat4x3 g, mat4x3 h)
{
return (dist4(a,b) + dist4(a,c) + dist4(d,e) + dist4(d,f) + 4.0*dist4(g,h));
}
void main()
{
vec4 edri, edr, edr_l, edr_u; // edr = edge detection rule, l = left, u = up.
vec4 irlv0, irlv1, irlv2l, irlv2u; // ir = interpolation restriction
vec3 A1 = texture(Source, t1.xw).rgb;
vec3 B1 = texture(Source, t1.yw).rgb;
vec3 C1 = texture(Source, t1.zw).rgb;
vec3 A = texture(Source, t2.xw).rgb;
vec3 B = texture(Source, t2.yw).rgb;
vec3 C = texture(Source, t2.zw).rgb;
vec3 D = texture(Source, t3.xw).rgb;
vec3 E = texture(Source, t3.yw).rgb;
vec3 F = texture(Source, t3.zw).rgb;
vec3 G = texture(Source, t4.xw).rgb;
vec3 H = texture(Source, t4.yw).rgb;
vec3 I = texture(Source, t4.zw).rgb;
vec3 G5 = texture(Source, t5.xw).rgb;
vec3 H5 = texture(Source, t5.yw).rgb;
vec3 I5 = texture(Source, t5.zw).rgb;
vec3 A0 = texture(Source, t6.xy).rgb;
vec3 D0 = texture(Source, t6.xz).rgb;
vec3 G0 = texture(Source, t6.xw).rgb;
vec3 C4 = texture(Source, t7.xy).rgb;
vec3 F4 = texture(Source, t7.xz).rgb;
vec3 I4 = texture(Source, t7.xw).rgb;
mat4x3 b = mat4x3(B, D, H, F);
mat4x3 c = mat4x3(C, A, G, I);
mat4x3 d = mat4x3(D, H, F, B);
mat4x3 e = mat4x3(E, E, E, E);
mat4x3 f = mat4x3(F, B, D, H);
mat4x3 g = mat4x3(G, I, C, A);
mat4x3 h = mat4x3(H, F, B, D);
mat4x3 i = mat4x3(I, C, A, G);
mat4x3 i4 = mat4x3(I4, C1, A0, G5);
mat4x3 i5 = mat4x3(I5, C4, A1, G0);
mat4x3 h5 = mat4x3(H5, F4, B1, D0);
mat4x3 f4 = mat4x3(F4, B1, D0, H5);
vec4 b_ = v2f * b;
vec4 c_ = v2f * c;
vec4 d_ = b_.yzwx;
vec4 e_ = v2f * e;
vec4 f_ = b_.wxyz;
vec4 g_ = c_.zwxy;
vec4 h_ = b_.zwxy;
vec4 i_ = c_.wxyz;
vec4 i4_ = v2f * i4;
vec4 i5_ = v2f * i5;
vec4 h5_ = v2f * h5;
vec4 f4_ = h5_.yzwx;
irlv0 = diff(e_, f_) * diff(e_, h_);
irlv1 = saturate( irlv0 * ( neq(f,b) * neq(f,c) + neq(h,d) * neq(h,g) + eq(e,i) * (neq(f,f4) * neq(f,i4) + neq(h,h5) * neq(h,i5)) + eq(e,g) + eq(e,c)) );
#ifdef CORNER_B
irlv1 = saturate(irlv0 * ( neq(f,b) * neq(h,d) + eq(e,i) * neq(f,i4) * neq(h,i5) + eq(e,g) + eq(e,c) ) );
#endif
#ifdef CORNER_C
irlv1 = saturate(irlv0 * ( neq(f,b) * neq(f,c) + neq(h,d) * neq(h,g) + eq(e,i) * (neq(f,f4) * neq(f,i4) + neq(h,h5) * neq(h,i5)) + eq(e,g) + eq(e,c)) );
#endif
irlv2l = diff(e_, g_) * diff(d_, g_);
irlv2u = diff(e_, c_) * diff(b_, c_);
vec4 wd1 = weighted_distance( e, c, g, i, h5, f4, h, f );
vec4 wd2 = weighted_distance( h, d, i5, f, i4, b, e, i );
vec4 d_fg = dist4(f, g);
vec4 d_hc = dist4(h, c);
edri = LTE(wd1, wd2) * irlv0;
edr = LT( wd1, wd2) * irlv1 * NOT(edri.yzwx * edri.wxyz);
edr_l = LTE( lv2_cf * d_fg, d_hc ) * irlv2l * edr * (NOT(edri.yzwx) * eq(e, c));
edr_u = LTE( lv2_cf * d_hc, d_fg ) * irlv2u * edr * (NOT(edri.wxyz) * eq(e, g));
vec4 info = zip * mat4(edr, edr_l, edr_u, edri);
FragColor = remapTo01(info, low, high);
}

View file

@ -0,0 +1,216 @@
#version 450
/*
Hyllian's xBR-lv2 - pass1 Shader
Copyright (C) 2011-2022 Hyllian - sergiogdb@gmail.com
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.
*/
layout(push_constant) uniform Push
{
float XBR_BLENDING;
} params;
#pragma parameter XBR_BLENDING "BLENDING [ NOBLEND | AA ]" 1.0 0.0 1.0 1.0
#define XBR_BLENDING params.XBR_BLENDING
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
} global;
#define saturate(c) clamp(c, 0.0, 1.0)
#define round(X) floor((X)+0.5)
const vec4 low = vec4( 0.0, 0.0, 0.0, 0.0);
const vec4 high = vec4(255.0, 255.0, 255.0, 255.0);
const vec3 Y = vec3(0.2627, 0.6780, 0.0593);
const vec4 Ao = vec4( 1.0, -1.0, -1.0, 1.0 );
const vec4 Bo = vec4( 1.0, 1.0, -1.0,-1.0 );
const vec4 Co = vec4( 1.5, 0.5, -0.5, 0.5 );
const vec4 Ax = vec4( 1.0, -1.0, -1.0, 1.0 );
const vec4 Bx = vec4( 0.5, 2.0, -0.5,-2.0 );
const vec4 Cx = vec4( 1.0, 1.0, -0.5, 0.0 );
const vec4 Ay = vec4( 1.0, -1.0, -1.0, 1.0 );
const vec4 By = vec4( 2.0, 0.5, -2.0,-0.5 );
const vec4 Cy = vec4( 2.0, 0.0, -1.0, 0.5 );
const vec4 Ci = vec4(0.25, 0.25, 0.25, 0.25);
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
layout(location = 1) out vec4 t1;
layout(location = 2) out vec4 t2;
layout(location = 3) out float aa_factor;
void main()
{
gl_Position = global.MVP * Position;
// vTexCoord = TexCoord;
vTexCoord = TexCoord * 1.0001;
float dx = global.SourceSize.z;
float dy = global.SourceSize.w;
// A1 B1 C1
// A0 A B C C4
// D0 D E F F4
// G0 G H I I4
// G5 H5 I5
aa_factor = 2.0*global.OutputSize.z * global.SourceSize.x;
t1 = vTexCoord.xyyy + vec4( 0, -dy, 0, dy); // B
t2 = vTexCoord.xxxy + vec4( -dx, 0, dx, 0); //D E F
// H
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 1) in vec4 t1;
layout(location = 2) in vec4 t2;
layout(location = 3) in float aa_factor;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
layout(set = 0, binding = 3) uniform sampler2D Original;
// Return if A components are less than or equal B ones.
vec4 LTE(vec4 A, vec4 B)
{
return step(A, B);
}
// Return if A components are less than B ones.
vec4 LT(vec4 A, vec4 B)
{
return vec4(lessThan(A, B));
}
float dist(vec3 A, vec3 B)
{
return dot(abs(A-B), Y);
}
// Calculate color distance between two vectors of four pixels
vec4 dist4(mat4x3 A, mat4x3 B)
{
return vec4(dist(A[0],B[0]), dist(A[1],B[1]), dist(A[2],B[2]), dist(A[3],B[3]));
}
vec4 remapFrom01(vec4 v, vec4 low, vec4 high)
{
return round(mix(low, high, v));
}
vec4 unpack_info(float i)
{
vec4 info;
info.x = round(modf(i/2.0, i));
info.y = round(modf(i/2.0, i));
info.z = round(modf(i/2.0, i));
info.w = i;
return info;
}
void main()
{
vec4 px; // px = pixel, edr = edge detection rule
vec4 edri, edr, edr_l, edr_u;
vec4 fx, fx_l, fx_u; // inequations of straight lines.
vec3 res1, res2;
vec4 fx45i, fx45, fx30, fx60;
vec2 fp = fract(vTexCoord*global.SourceSize.xy);
vec3 B = texture(Original, t1.xy).rgb;
vec3 D = texture(Original, t2.xw).rgb;
vec3 E = texture(Original, t2.yw).rgb;
vec3 F = texture(Original, t2.zw).rgb;
vec3 H = texture(Original, t1.xw).rgb;
mat4x3 b = mat4x3(B, D, H, F);
mat4x3 e = mat4x3(E, E, E, E);
mat4x3 d = mat4x3(D, H, F, B);
mat4x3 f = mat4x3(F, B, D, H);
mat4x3 h = mat4x3(H, F, B, D);
// These inequations define the line below which interpolation occurs.
fx = (Ao*fp.y+Bo*fp.x);
fx_l = (Ax*fp.y+Bx*fp.x);
fx_u = (Ay*fp.y+By*fp.x);
if (XBR_BLENDING == 1.0) {
vec4 delta = vec4(aa_factor);
vec4 deltaL = vec4(0.5, 1.0, 0.5, 1.0) * aa_factor;
vec4 deltaU = deltaL.yxwz;
fx45i = saturate( 0.5 + (fx - Co - Ci) / delta );
fx45 = saturate( 0.5 + (fx - Co ) / delta );
fx30 = saturate( 0.5 + (fx_l - Cx ) / deltaL );
fx60 = saturate( 0.5 + (fx_u - Cy ) / deltaU );
}
else {
fx45i = LT( Co + Ci, fx );
fx45 = LT( Co, fx );
fx30 = LT( Cx, fx_l );
fx60 = LT( Cy, fx_u );
}
vec4 info = texture(Source, vTexCoord);
vec4 i = remapFrom01(info, low, high);
edr = unpack_info(i.x);
edr_l = unpack_info(i.y);
edr_u = unpack_info(i.z);
edri = unpack_info(i.w);
fx45i = edri*fx45i;
fx45 = edr*fx45;
fx30 = edr_l*fx30;
fx60 = edr_u*fx60;
px = LTE(dist4(e,f), dist4(e,h));
vec4 maximos = max(max(fx30, fx60), max(fx45, fx45i));
res1 = mix(E, mix(H, F, px.x), maximos.x);
res2 = mix(E, mix(B, D, px.z), maximos.z);
vec3 res1a = mix(res1, res2, step(dist(E, res1), dist(E, res2)));
res1 = mix(E, mix(F, B, px.y), maximos.y);
res2 = mix(E, mix(D, H, px.w), maximos.w);
vec3 res1b = mix(res1, res2, step(dist(E, res1), dist(E, res2)));
vec3 res = mix(res1a, res1b, step(dist(E, res1a), dist(E, res1b)));
FragColor = vec4(res, 1.0);
}

View file

@ -3,7 +3,7 @@
/* /*
Hyllian's xBR-lv2 Shader Hyllian's xBR-lv2 Shader
Copyright (C) 2011-2015 Hyllian - sergiogdb@gmail.com Copyright (C) 2011-2022 Hyllian - sergiogdb@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the copy of this software and associated documentation files (the
@ -33,26 +33,18 @@ layout(push_constant) uniform Push
vec4 OriginalSize; vec4 OriginalSize;
vec4 OutputSize; vec4 OutputSize;
uint FrameCount; uint FrameCount;
float XBR_Y_WEIGHT;
float XBR_EQ_THRESHOLD; float XBR_EQ_THRESHOLD;
float XBR_LV1_COEFFICIENT;
float XBR_LV2_COEFFICIENT; float XBR_LV2_COEFFICIENT;
float small_details; float XBR_BLENDING;
} params; } params;
#pragma parameter XBR_Y_WEIGHT "Y Weight" 48.0 0.0 100.0 1.0 #pragma parameter XBR_EQ_THRESHOLD "COLOR DISTINCTION THRESHOLD" 0.32 0.0 1.0 0.01
#pragma parameter XBR_EQ_THRESHOLD "Eq Threshold" 15.0 0.0 50.0 1.0 #pragma parameter XBR_LV2_COEFFICIENT "SMOOTHNESS THRESHOLD" 0.30 0.0 1.0 0.1
#pragma parameter XBR_LV1_COEFFICIENT "Lv1 Coefficient" 0.5 0.0 30.0 0.5 #pragma parameter XBR_BLENDING "BLENDING [ NOBLEND | AA ]" 1.0 0.0 1.0 1.0
#pragma parameter XBR_LV2_COEFFICIENT "Lv2 Coefficient" 2.0 1.0 3.0 0.1
#pragma parameter small_details "Preserve Small Details" 0.0 0.0 1.0 1.0
#define XBR_Y_WEIGHT params.XBR_Y_WEIGHT
#define XBR_EQ_THRESHOLD params.XBR_EQ_THRESHOLD #define XBR_EQ_THRESHOLD params.XBR_EQ_THRESHOLD
#define XBR_LV1_COEFFICIENT params.XBR_LV1_COEFFICIENT
#define XBR_LV2_COEFFICIENT params.XBR_LV2_COEFFICIENT #define XBR_LV2_COEFFICIENT params.XBR_LV2_COEFFICIENT
#define small_details params.small_details #define XBR_BLENDING params.XBR_BLENDING
#define mul(a,b) (b*a)
layout(std140, set = 0, binding = 0) uniform UBO layout(std140, set = 0, binding = 0) uniform UBO
{ {
@ -63,23 +55,9 @@ layout(std140, set = 0, binding = 0) uniform UBO
//#define CORNER_A //#define CORNER_A
//#define CORNER_B //#define CORNER_B
#define CORNER_C #define CORNER_C
//#define CORNER_D
#ifndef CORNER_A #define lv2_cf (XBR_LV2_COEFFICIENT + 2.0)
#define SMOOTH_TIPS #define saturate(c) clamp(c, 0.0, 1.0)
#endif
#define XBR_SCALE 3.0
#define lv2_cf XBR_LV2_COEFFICIENT
const float coef = 2.0;
const vec3 rgbw = vec3(14.352, 28.176, 5.472);
const vec4 eq_threshold = vec4(15.0, 15.0, 15.0, 15.0);
const vec4 delta = vec4(1.0/XBR_SCALE, 1.0/XBR_SCALE, 1.0/XBR_SCALE, 1.0/XBR_SCALE);
const vec4 delta_l = vec4(0.5/XBR_SCALE, 1.0/XBR_SCALE, 0.5/XBR_SCALE, 1.0/XBR_SCALE);
const vec4 delta_u = delta_l.yxwz;
const vec4 Ao = vec4( 1.0, -1.0, -1.0, 1.0 ); const vec4 Ao = vec4( 1.0, -1.0, -1.0, 1.0 );
const vec4 Bo = vec4( 1.0, 1.0, -1.0,-1.0 ); const vec4 Bo = vec4( 1.0, 1.0, -1.0,-1.0 );
@ -92,12 +70,25 @@ const vec4 By = vec4( 2.0, 0.5, -2.0,-0.5 );
const vec4 Cy = vec4( 2.0, 0.0, -1.0, 0.5 ); const vec4 Cy = vec4( 2.0, 0.0, -1.0, 0.5 );
const vec4 Ci = vec4(0.25, 0.25, 0.25, 0.25); const vec4 Ci = vec4(0.25, 0.25, 0.25, 0.25);
const vec3 Y = vec3(0.2126, 0.7152, 0.0722); const vec3 v2f = vec3( 65536, 256, 1); // vec to float encode
const vec3 Y = vec3(0.2627, 0.6780, 0.0593);
// Difference between vector components. // Return if A components are less than or equal B ones.
vec4 df(vec4 A, vec4 B) vec4 LTE(vec4 A, vec4 B)
{ {
return vec4(abs(A-B)); return step(A, B);
}
// Return if A components are less than B ones.
vec4 LT(vec4 A, vec4 B)
{
return vec4(lessThan(A, B));
}
// Return logically inverted vector components. BEWARE: Only works with 0.0 or 1.0 components.
vec4 NOT(vec4 A)
{
return (vec4(1.0) - A);
} }
// Compare two vectors and return their components are different. // Compare two vectors and return their components are different.
@ -106,34 +97,35 @@ vec4 diff(vec4 A, vec4 B)
return vec4(notEqual(A, B)); return vec4(notEqual(A, B));
} }
// Determine if two vector components are equal based on a threshold. float dist(vec3 A, vec3 B)
vec4 eq(vec4 A, vec4 B)
{ {
return (step(df(A, B), vec4(XBR_EQ_THRESHOLD))); return dot(abs(A-B), Y);
}
// Calculate color distance between two vectors of four pixels
vec4 dist4(mat4x3 A, mat4x3 B)
{
return vec4(dist(A[0],B[0]), dist(A[1],B[1]), dist(A[2],B[2]), dist(A[3],B[3]));
}
// Tests if color components are under a threshold. In this case they are considered 'equal'.
vec4 eq(mat4x3 A, mat4x3 B)
{
return (step(dist4(A, B), vec4(XBR_EQ_THRESHOLD)));
} }
// Determine if two vector components are NOT equal based on a threshold. // Determine if two vector components are NOT equal based on a threshold.
vec4 neq(vec4 A, vec4 B) vec4 neq(mat4x3 A, mat4x3 B)
{ {
return (vec4(1.0, 1.0, 1.0, 1.0) - eq(A, B)); return (vec4(1.0, 1.0, 1.0, 1.0) - eq(A, B));
} }
// Weighted distance. // Calculate weighted distance among pixels in some directions.
vec4 wd(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h) vec4 weighted_distance(mat4x3 a, mat4x3 b, mat4x3 c, mat4x3 d, mat4x3 e, mat4x3 f, mat4x3 g, mat4x3 h)
{ {
return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h)); return (dist4(a,b) + dist4(a,c) + dist4(d,e) + dist4(d,f) + 4.0*dist4(g,h));
} }
vec4 weighted_distance(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h, vec4 i, vec4 j, vec4 k, vec4 l)
{
return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + df(i,j) + df(k,l) + 2.0*df(g,h));
}
float c_df(vec3 c1, vec3 c2)
{
vec3 df = abs(c1 - c2);
return df.r + df.g + df.b;
}
#pragma stage vertex #pragma stage vertex
layout(location = 0) in vec4 Position; layout(location = 0) in vec4 Position;
@ -146,23 +138,31 @@ layout(location = 4) out vec4 t4;
layout(location = 5) out vec4 t5; layout(location = 5) out vec4 t5;
layout(location = 6) out vec4 t6; layout(location = 6) out vec4 t6;
layout(location = 7) out vec4 t7; layout(location = 7) out vec4 t7;
layout(location = 8) out float aa_factor;
void main() void main()
{ {
gl_Position = global.MVP * Position; gl_Position = global.MVP * Position;
texCoord = TexCoord; texCoord = TexCoord * 1.0001;
aa_factor = 2.0*params.OutputSize.z * params.SourceSize.x;
float dx = params.SourceSize.z; float dx = params.SourceSize.z;
float dy = params.SourceSize.w; float dy = params.SourceSize.w;
t1 = TexCoord.xxxy + vec4( -dx, 0, dx,-2.0*dy); // A1 B1 C1 // A1 B1 C1
t2 = TexCoord.xxxy + vec4( -dx, 0, dx, -dy); // A B C // A0 A B C C4
t3 = TexCoord.xxxy + vec4( -dx, 0, dx, 0); // D E F // D0 D E F F4
t4 = TexCoord.xxxy + vec4( -dx, 0, dx, dy); // G H I // G0 G H I I4
t5 = TexCoord.xxxy + vec4( -dx, 0, dx, 2.0*dy); // G5 H5 I5 // G5 H5 I5
t6 = TexCoord.xyyy + vec4(-2.0*dx,-dy, 0, dy); // A0 D0 G0
t7 = TexCoord.xyyy + vec4( 2.0*dx,-dy, 0, dy); // C4 F4 I4 t1 = texCoord.xxxy + vec4( -dx, 0, dx,-2.0*dy); // A1 B1 C1
t2 = texCoord.xxxy + vec4( -dx, 0, dx, -dy); // A B C
t3 = texCoord.xxxy + vec4( -dx, 0, dx, 0); // D E F
t4 = texCoord.xxxy + vec4( -dx, 0, dx, dy); // G H I
t5 = texCoord.xxxy + vec4( -dx, 0, dx, 2.0*dy); // G5 H5 I5
t6 = texCoord.xyyy + vec4(-2.0*dx,-dy, 0, dy); // A0 D0 G0
t7 = texCoord.xyyy + vec4( 2.0*dx,-dy, 0, dy); // C4 F4 I4
} }
#pragma stage fragment #pragma stage fragment
@ -174,14 +174,17 @@ layout(location = 4) in vec4 t4;
layout(location = 5) in vec4 t5; layout(location = 5) in vec4 t5;
layout(location = 6) in vec4 t6; layout(location = 6) in vec4 t6;
layout(location = 7) in vec4 t7; layout(location = 7) in vec4 t7;
layout(location = 8) in float aa_factor;
layout(location = 0) out vec4 FragColor; layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source; layout(set = 0, binding = 2) uniform sampler2D Source;
void main() void main()
{ {
vec4 edri, edr, edr_l, edr_u, px; // px = pixel, edr = edge detection rule vec4 edri, edr, edr_l, edr_u, px; // px = pixel, edr = edge detection rule
vec4 irlv0, irlv1, irlv2l, irlv2u, block_3d; vec4 irlv0, irlv1, irlv2l, irlv2u;
vec4 fx, fx_l, fx_u; // inequations of straight lines. vec4 fx, fx_l, fx_u; // inequations of straight lines.
vec3 res1, res2;
vec4 fx45i, fx45, fx30, fx60;
vec2 fp = fract(texCoord*params.SourceSize.xy); vec2 fp = fract(texCoord*params.SourceSize.xy);
@ -207,100 +210,100 @@ void main()
vec3 F4 = texture(Source, t7.xz ).xyz; vec3 F4 = texture(Source, t7.xz ).xyz;
vec3 I4 = texture(Source, t7.xw ).xyz; vec3 I4 = texture(Source, t7.xw ).xyz;
vec4 b = vec4(dot(B ,rgbw), dot(D ,rgbw), dot(H ,rgbw), dot(F ,rgbw)); mat4x3 b = mat4x3(B, D, H, F);
vec4 c = vec4(dot(C ,rgbw), dot(A ,rgbw), dot(G ,rgbw), dot(I ,rgbw)); mat4x3 c = mat4x3(C, A, G, I);
vec4 d = b.yzwx; mat4x3 d = mat4x3(D, H, F, B);
vec4 e = vec4(dot(E,rgbw)); mat4x3 e = mat4x3(E, E, E, E);
vec4 f = b.wxyz; mat4x3 f = mat4x3(F, B, D, H);
vec4 g = c.zwxy; mat4x3 g = mat4x3(G, I, C, A);
vec4 h = b.zwxy; mat4x3 h = mat4x3(H, F, B, D);
vec4 i = c.wxyz; mat4x3 i = mat4x3(I, C, A, G);
vec4 i4, i5, h5, f4; mat4x3 i4 = mat4x3(I4, C1, A0, G5);
mat4x3 i5 = mat4x3(I5, C4, A1, G0);
mat4x3 h5 = mat4x3(H5, F4, B1, D0);
mat4x3 f4 = mat4x3(F4, B1, D0, H5);
float y_weight = XBR_Y_WEIGHT; vec4 b_ = v2f * b;
vec4 c_ = v2f * c;
vec4 d_ = b_.yzwx;
vec4 e_ = v2f * e;
vec4 f_ = b_.wxyz;
vec4 g_ = c_.zwxy;
vec4 h_ = b_.zwxy;
vec4 i_ = c_.wxyz;
if (small_details < 0.5) vec4 i4_ = v2f * i4;
{ vec4 i5_ = v2f * i5;
i4 = vec4(dot(I4,rgbw), dot(C1,rgbw), dot(A0,rgbw), dot(G5,rgbw)); vec4 h5_ = v2f * h5;
i5 = vec4(dot(I5,rgbw), dot(C4,rgbw), dot(A1,rgbw), dot(G0,rgbw)); vec4 f4_ = h5_.yzwx;
h5 = vec4(dot(H5,rgbw), dot(F4,rgbw), dot(B1,rgbw), dot(D0,rgbw));
}
else
{
i4 = mul( mat4x3(I4, C1, A0, G5), y_weight * Y );
i5 = mul( mat4x3(I5, C4, A1, G0), y_weight * Y );
h5 = mul( mat4x3(H5, F4, B1, D0), y_weight * Y );
}
f4 = h5.yzwx;
// These inequations define the line below which interpolation occurs. // These inequations define the line below which interpolation occurs.
fx = ( Ao*fp.y + Bo*fp.x ); fx = ( Ao*fp.y + Bo*fp.x );
fx_l = ( Ax*fp.y + Bx*fp.x ); fx_l = ( Ax*fp.y + Bx*fp.x );
fx_u = ( Ay*fp.y + By*fp.x ); fx_u = ( Ay*fp.y + By*fp.x );
irlv1 = irlv0 = diff(e,f) * diff(e,h); irlv0 = diff(e_,f_) * diff(e_,h_);
irlv1 = irlv0;
#ifdef CORNER_B #ifdef CORNER_B
irlv1 = (irlv0 * ( neq(f,b) * neq(h,d) + eq(e,i) * neq(f,i4) * neq(h,i5) + eq(e,g) + eq(e,c) ) ); irlv1 = saturate(irlv0 * ( neq(f,b) * neq(h,d) + eq(e,i) * neq(f,i4) * neq(h,i5) + eq(e,g) + eq(e,c) ) );
#endif
#ifdef CORNER_D
vec4 c1 = i4.yzwx;
vec4 g0 = i5.wxyz;
irlv1 = (irlv0 * ( neq(f,b) * neq(h,d) + eq(e,i) * neq(f,i4) * neq(h,i5) + eq(e,g) + eq(e,c) ) * (diff(f,f4) * diff(f,i) + diff(h,h5) * diff(h,i) + diff(h,g) + diff(f,c) + eq(b,c1) * eq(d,g0)));
#endif #endif
#ifdef CORNER_C #ifdef CORNER_C
irlv1 = (irlv0 * ( neq(f,b) * neq(f,c) + neq(h,d) * neq(h,g) + eq(e,i) * (neq(f,f4) * neq(f,i4) + neq(h,h5) * neq(h,i5)) + eq(e,g) + eq(e,c)) ); irlv1 = saturate(irlv0 * ( neq(f,b) * neq(f,c) + neq(h,d) * neq(h,g) + eq(e,i) * (neq(f,f4) * neq(f,i4) + neq(h,h5) * neq(h,i5)) + eq(e,g) + eq(e,c)) );
#endif #endif
irlv2l = diff(e,g) * diff(d,g); irlv2l = diff(e_,g_) * diff( d_, g_);
irlv2u = diff(e,c) * diff(b,c); irlv2u = diff(e_,c_) * diff( b_, c_);
vec4 fx45i = clamp((fx + delta -Co - Ci)/(2.0*delta ), 0.0, 1.0); if (XBR_BLENDING == 1.0) {
vec4 fx45 = clamp((fx + delta -Co )/(2.0*delta ), 0.0, 1.0); vec4 delta = vec4(aa_factor);
vec4 fx30 = clamp((fx_l + delta_l -Cx )/(2.0*delta_l), 0.0, 1.0); vec4 deltaL = vec4(0.5, 1.0, 0.5, 1.0) * aa_factor;
vec4 fx60 = clamp((fx_u + delta_u -Cy )/(2.0*delta_u), 0.0, 1.0); vec4 deltaU = deltaL.yxwz;
vec4 wd1, wd2; fx45i = saturate( 0.5 + (fx - Co - Ci) / delta );
if (small_details < 0.5) fx45 = saturate( 0.5 + (fx - Co ) / delta );
{ fx30 = saturate( 0.5 + (fx_l - Cx ) / deltaL );
wd1 = wd( e, c, g, i, h5, f4, h, f); fx60 = saturate( 0.5 + (fx_u - Cy ) / deltaU );
wd2 = wd( h, d, i5, f, i4, b, e, i);
} }
else else {
{ fx45i = LT( Co + Ci, fx );
wd1 = weighted_distance( e, c, g, i, f4, h5, h, f, b, d, i4, i5); fx45 = LT( Co, fx );
wd2 = weighted_distance( h, d, i5, f, b, i4, e, i, g, h5, c, f4); fx30 = LT( Cx, fx_l );
fx60 = LT( Cy, fx_u );
} }
edri = step(wd1, wd2) * irlv0; vec4 wd1 = weighted_distance( e, c, g, i, h5, f4, h, f);
edr = step(wd1 + vec4(0.1, 0.1, 0.1, 0.1), wd2) * step(vec4(0.5, 0.5, 0.5, 0.5), irlv1); vec4 wd2 = weighted_distance( h, d, i5, f, i4, b, e, i);
edr_l = step( lv2_cf*df(f,g), df(h,c) ) * irlv2l * edr;
edr_u = step( lv2_cf*df(h,c), df(f,g) ) * irlv2u * edr;
vec4 d_fg = dist4(f, g);
vec4 d_hc = dist4(h, c);
edri = LTE(wd1, wd2) * irlv0;
edr = LT( wd1, wd2) * irlv1 * NOT(edri.yzwx * edri.wxyz);
edr_l = LTE( lv2_cf * d_fg, d_hc ) * irlv2l * edr * (NOT(edri.yzwx) * eq(e, c));
edr_u = LTE( lv2_cf * d_hc, d_fg ) * irlv2u * edr * (NOT(edri.wxyz) * eq(e, g));
fx45i = edri * fx45i;
fx45 = edr * fx45; fx45 = edr * fx45;
fx30 = edr_l * fx30; fx30 = edr_l * fx30;
fx60 = edr_u * fx60; fx60 = edr_u * fx60;
fx45i = edri * fx45i;
px = step(df(e,f), df(e,h)); px = LTE(dist4(e,f), dist4(e,h));
#ifdef SMOOTH_TIPS
vec4 maximos = max(max(fx30, fx60), max(fx45, fx45i)); vec4 maximos = max(max(fx30, fx60), max(fx45, fx45i));
#endif
#ifndef SMOOTH_TIPS
vec4 maximos = max(max(fx30, fx60), fx45);
#endif
vec3 res1 = E; res1 = mix(E, mix(H, F, px.x), maximos.x);
res1 = mix(res1, mix(H, F, px.x), maximos.x); res2 = mix(E, mix(B, D, px.z), maximos.z);
res1 = mix(res1, mix(B, D, px.z), maximos.z);
vec3 res2 = E; vec3 res1a = mix(res1, res2, step(dist(E, res1), dist(E, res2)));
res2 = mix(res2, mix(F, B, px.y), maximos.y);
res2 = mix(res2, mix(D, H, px.w), maximos.w);
vec3 res = mix(res1, res2, step(c_df(E, res1), c_df(E, res2))); res1 = mix(E, mix(F, B, px.y), maximos.y);
res2 = mix(E, mix(D, H, px.w), maximos.w);
vec3 res1b = mix(res1, res2, step(dist(E, res1), dist(E, res2)));
vec3 res = mix(res1a, res1b, step(dist(E, res1a), dist(E, res1b)));
FragColor = vec4(res, 1.0); FragColor = vec4(res, 1.0);
} }

View file

@ -1,71 +1,149 @@
#version 450 #version 450
/*
Hyllian's xBR-lv3 Shader
Copyright (C) 2011-2022 Hyllian - sergiogdb@gmail.com
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.
Incorporates some of the ideas from SABR shader. Thanks to Joshua Street.
*/
layout(push_constant) uniform Push layout(push_constant) uniform Push
{ {
vec4 SourceSize; vec4 SourceSize;
vec4 OriginalSize; vec4 OriginalSize;
vec4 OutputSize; vec4 OutputSize;
uint FrameCount; uint FrameCount;
float XBR_Y_WEIGHT;
float XBR_EQ_THRESHOLD; float XBR_EQ_THRESHOLD;
float XBR_EQ_THRESHOLD2;
float XBR_LV2_COEFFICIENT; float XBR_LV2_COEFFICIENT;
float corner_type; float XBR_BLENDING;
} params; } params;
#pragma parameter XBR_Y_WEIGHT "Y Weight" 48.0 0.0 100.0 1.0 #pragma parameter XBR_EQ_THRESHOLD "COLOR DISTINCTION THRESHOLD" 0.32 0.0 1.0 0.01
#pragma parameter XBR_EQ_THRESHOLD "EQ Threshold" 10.0 0.0 50.0 1.0 #pragma parameter XBR_LV2_COEFFICIENT "SMOOTHNESS THRESHOLD" 0.30 0.0 1.0 0.1
#pragma parameter XBR_EQ_THRESHOLD2 "EQ Threshold 2" 2.0 0.0 4.0 1.0 #pragma parameter XBR_BLENDING "BLENDING [ NOBLEND | AA ]" 1.0 0.0 1.0 1.0
#pragma parameter XBR_LV2_COEFFICIENT "Lv2 Coefficient" 2.0 1.0 3.0 1.0
#pragma parameter corner_type "Corner Calculation" 3.0 1.0 3.0 1.0 #define XBR_EQ_THRESHOLD params.XBR_EQ_THRESHOLD
#define XBR_LV2_COEFFICIENT params.XBR_LV2_COEFFICIENT
#define XBR_BLENDING params.XBR_BLENDING
layout(std140, set = 0, binding = 0) uniform UBO layout(std140, set = 0, binding = 0) uniform UBO
{ {
mat4 MVP; mat4 MVP;
} global; } global;
const mat3 yuv = mat3(0.299, 0.587, 0.114, -0.169, -0.331, 0.499, 0.499, -0.418, -0.0813); // Uncomment just one of the three params below to choose the corner detection
const vec4 delta = vec4(0.4, 0.4, 0.4, 0.4); //#define CORNER_A
//#define CORNER_B
#define CORNER_C
vec4 df(vec4 A, vec4 B) #define XBR_EQ_THRESHOLD2 0.02
#define lv2_cf (XBR_LV2_COEFFICIENT + 2.0)
#define saturate(c) clamp(c, 0.0, 1.0)
const vec4 Ao = vec4( 1.0, -1.0, -1.0, 1.0 );
const vec4 Bo = vec4( 1.0, 1.0, -1.0,-1.0 );
const vec4 Co = vec4( 1.5, 0.5, -0.5, 0.5 );
const vec4 Ax = vec4( 1.0, -1.0, -1.0, 1.0 );
const vec4 Bx = vec4( 0.5, 2.0, -0.5,-2.0 );
const vec4 Cx = vec4( 1.0, 1.0, -0.5, 0.0 );
const vec4 Ay = vec4( 1.0, -1.0, -1.0, 1.0 );
const vec4 By = vec4( 2.0, 0.5, -2.0,-0.5 );
const vec4 Cy = vec4( 2.0, 0.0, -1.0, 0.5 );
const vec4 Ci = vec4(0.25, 0.25, 0.25, 0.25);
const vec4 Az = vec4( 6.0, -2.0, -6.0, 2.0 );
const vec4 Bz = vec4( 2.0, 6.0, -2.0, -6.0 );
const vec4 Cz = vec4( 5.0, 3.0, -3.0, -1.0 );
const vec4 Aw = vec4( 2.0, -6.0, -2.0, 6.0 );
const vec4 Bw = vec4( 6.0, 2.0, -6.0,-2.0 );
const vec4 Cw = vec4( 5.0, -1.0, -3.0, 3.0 );
const vec3 v2f = vec3( 65536, 256, 1); // vec to float encode
const vec3 Y = vec3(0.2627, 0.6780, 0.0593);
// Return if A components are less than or equal B ones.
vec4 LTE(vec4 A, vec4 B)
{ {
return vec4(abs(A-B)); return step(A, B);
} }
float c_df(vec3 c1, vec3 c2) { // Return if A components are less than B ones.
vec3 df = abs(c1 - c2); vec4 LT(vec4 A, vec4 B)
return df.r + df.g + df.b;
}
bvec4 eq(vec4 A, vec4 B)
{ {
return lessThan(df(A, B), vec4(params.XBR_EQ_THRESHOLD)); return vec4(lessThan(A, B));
} }
bvec4 eq2(vec4 A, vec4 B) // Return logically inverted vector components. BEWARE: Only works with 0.0 or 1.0 components.
vec4 NOT(vec4 A)
{ {
return lessThan(df(A, B), vec4(params.XBR_EQ_THRESHOLD2)); return (vec4(1.0) - A);
} }
bvec4 and(bvec4 A, bvec4 B) // Compare two vectors and return their components are different.
vec4 diff(vec4 A, vec4 B)
{ {
return bvec4(A.x && B.x, A.y && B.y, A.z && B.z, A.w && B.w); return vec4(notEqual(A, B));
} }
bvec4 or(bvec4 A, bvec4 B) float dist(vec3 A, vec3 B)
{ {
return bvec4(A.x || B.x, A.y || B.y, A.z || B.z, A.w || B.w); return dot(abs(A-B), Y);
} }
vec4 weighted_distance(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h) // Calculate color distance between two vectors of four pixels
vec4 dist4(mat4x3 A, mat4x3 B)
{ {
return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h)); return vec4(dist(A[0],B[0]), dist(A[1],B[1]), dist(A[2],B[2]), dist(A[3],B[3]));
} }
// Tests if color components are under a threshold. In this case they are considered 'equal'.
vec4 eq(mat4x3 A, mat4x3 B)
{
return (step(dist4(A, B), vec4(XBR_EQ_THRESHOLD)));
}
vec4 eq2(mat4x3 A, mat4x3 B)
{
return (step(dist4(A, B), vec4(XBR_EQ_THRESHOLD2)));
}
// Determine if two vector components are NOT equal based on a threshold.
vec4 neq(mat4x3 A, mat4x3 B)
{
return (vec4(1.0, 1.0, 1.0, 1.0) - eq(A, B));
}
// Calculate weighted distance among pixels in some directions.
vec4 weighted_distance(mat4x3 a, mat4x3 b, mat4x3 c, mat4x3 d, mat4x3 e, mat4x3 f, mat4x3 g, mat4x3 h)
{
return (dist4(a,b) + dist4(a,c) + dist4(d,e) + dist4(d,f) + 4.0*dist4(g,h));
}
#pragma stage vertex #pragma stage vertex
layout(location = 0) in vec4 Position; layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord; layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord; layout(location = 0) out vec2 texCoord;
layout(location = 1) out vec4 t1; layout(location = 1) out vec4 t1;
layout(location = 2) out vec4 t2; layout(location = 2) out vec4 t2;
layout(location = 3) out vec4 t3; layout(location = 3) out vec4 t3;
@ -73,15 +151,17 @@ layout(location = 4) out vec4 t4;
layout(location = 5) out vec4 t5; layout(location = 5) out vec4 t5;
layout(location = 6) out vec4 t6; layout(location = 6) out vec4 t6;
layout(location = 7) out vec4 t7; layout(location = 7) out vec4 t7;
layout(location = 8) out float aa_factor;
void main() void main()
{ {
gl_Position = global.MVP * Position; gl_Position = global.MVP * Position;
vTexCoord = TexCoord * 1.0004; texCoord = TexCoord * 1.0001;
vec2 ps = vec2(1.0) / params.SourceSize.xy; aa_factor = 2.0*params.OutputSize.z * params.SourceSize.x;
float dx = ps.x;
float dy = ps.y; float dx = params.SourceSize.z;
float dy = params.SourceSize.w;
// A1 B1 C1 // A1 B1 C1
// A0 A B C C4 // A0 A B C C4
@ -89,17 +169,17 @@ void main()
// G0 G H I I4 // G0 G H I I4
// G5 H5 I5 // G5 H5 I5
t1 = vTexCoord.xxxy + vec4( -dx, 0, dx,-2.0*dy); // A1 B1 C1 t1 = texCoord.xxxy + vec4( -dx, 0, dx,-2.0*dy); // A1 B1 C1
t2 = vTexCoord.xxxy + vec4( -dx, 0, dx, -dy); // A B C t2 = texCoord.xxxy + vec4( -dx, 0, dx, -dy); // A B C
t3 = vTexCoord.xxxy + vec4( -dx, 0, dx, 0); // D E F t3 = texCoord.xxxy + vec4( -dx, 0, dx, 0); // D E F
t4 = vTexCoord.xxxy + vec4( -dx, 0, dx, dy); // G H I t4 = texCoord.xxxy + vec4( -dx, 0, dx, dy); // G H I
t5 = vTexCoord.xxxy + vec4( -dx, 0, dx, 2.0*dy); // G5 H5 I5 t5 = texCoord.xxxy + vec4( -dx, 0, dx, 2.0*dy); // G5 H5 I5
t6 = vTexCoord.xyyy + vec4(-2.0*dx,-dy, 0, dy); // A0 D0 G0 t6 = texCoord.xyyy + vec4(-2.0*dx,-dy, 0, dy); // A0 D0 G0
t7 = vTexCoord.xyyy + vec4( 2.0*dx,-dy, 0, dy); // C4 F4 I4 t7 = texCoord.xyyy + vec4( 2.0*dx,-dy, 0, dy); // C4 F4 I4
} }
#pragma stage fragment #pragma stage fragment
layout(location = 0) in vec2 vTexCoord; layout(location = 0) in vec2 texCoord;
layout(location = 1) in vec4 t1; layout(location = 1) in vec4 t1;
layout(location = 2) in vec4 t2; layout(location = 2) in vec4 t2;
layout(location = 3) in vec4 t3; layout(location = 3) in vec4 t3;
@ -107,162 +187,164 @@ layout(location = 4) in vec4 t4;
layout(location = 5) in vec4 t5; layout(location = 5) in vec4 t5;
layout(location = 6) in vec4 t6; layout(location = 6) in vec4 t6;
layout(location = 7) in vec4 t7; layout(location = 7) in vec4 t7;
layout(location = 8) in float aa_factor;
layout(location = 0) out vec4 FragColor; layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source; layout(set = 0, binding = 2) uniform sampler2D Source;
void main() void main()
{ {
bvec4 edr, edr_left, edr_up, edr3_left, edr3_up, px; // px = pixel, edr = edge detection rule vec4 edri, edr, edr_l, edr_u, edr3_l, edr3_u, px; // px = pixel, edr = edge detection rule
bvec4 interp_restriction_lv1, interp_restriction_lv2_left, interp_restriction_lv2_up; vec4 irlv0, irlv1, irlv2l, irlv2u, irlv3l, irlv3u;
bvec4 interp_restriction_lv3_left, interp_restriction_lv3_up; vec4 fx, fx_l, fx_u, fx3_l, fx3_u; // inequations of straight lines.
bvec4 nc, nc30, nc60, nc45, nc15, nc75; // new_color vec3 res1, res2;
vec4 fx, fx_left, fx_up, finalfx, fx3_left, fx3_up; // inequations of straight lines. vec4 fx45i, fx45, fx30, fx60, fx15, fx75;
vec3 res1, res2, pix1, pix2;
float blend1, blend2;
vec2 fp = fract(vTexCoord * params.SourceSize.xy); vec2 fp = fract(texCoord*params.SourceSize.xy);
vec3 A1 = texture(Source, t1.xw).rgb; vec3 A1 = texture(Source, t1.xw ).xyz;
vec3 B1 = texture(Source, t1.yw).rgb; vec3 B1 = texture(Source, t1.yw ).xyz;
vec3 C1 = texture(Source, t1.zw).rgb; vec3 C1 = texture(Source, t1.zw ).xyz;
vec3 A = texture(Source, t2.xw ).xyz;
vec3 B = texture(Source, t2.yw ).xyz;
vec3 C = texture(Source, t2.zw ).xyz;
vec3 D = texture(Source, t3.xw ).xyz;
vec3 E = texture(Source, t3.yw ).xyz;
vec3 F = texture(Source, t3.zw ).xyz;
vec3 G = texture(Source, t4.xw ).xyz;
vec3 H = texture(Source, t4.yw ).xyz;
vec3 I = texture(Source, t4.zw ).xyz;
vec3 G5 = texture(Source, t5.xw ).xyz;
vec3 H5 = texture(Source, t5.yw ).xyz;
vec3 I5 = texture(Source, t5.zw ).xyz;
vec3 A0 = texture(Source, t6.xy ).xyz;
vec3 D0 = texture(Source, t6.xz ).xyz;
vec3 G0 = texture(Source, t6.xw ).xyz;
vec3 C4 = texture(Source, t7.xy ).xyz;
vec3 F4 = texture(Source, t7.xz ).xyz;
vec3 I4 = texture(Source, t7.xw ).xyz;
vec3 A = texture(Source, t2.xw).rgb; mat4x3 b = mat4x3(B, D, H, F);
vec3 B = texture(Source, t2.yw).rgb; mat4x3 c = mat4x3(C, A, G, I);
vec3 C = texture(Source, t2.zw).rgb; mat4x3 d = mat4x3(D, H, F, B);
mat4x3 e = mat4x3(E, E, E, E);
mat4x3 f = mat4x3(F, B, D, H);
mat4x3 g = mat4x3(G, I, C, A);
mat4x3 h = mat4x3(H, F, B, D);
mat4x3 i = mat4x3(I, C, A, G);
vec3 D = texture(Source, t3.xw).rgb; mat4x3 i4 = mat4x3(I4, C1, A0, G5);
vec3 E = texture(Source, t3.yw).rgb; mat4x3 i5 = mat4x3(I5, C4, A1, G0);
vec3 F = texture(Source, t3.zw).rgb; mat4x3 h5 = mat4x3(H5, F4, B1, D0);
mat4x3 f4 = mat4x3(F4, B1, D0, H5);
vec3 G = texture(Source, t4.xw).rgb; mat4x3 c4 = mat4x3(C4, A1, G0, I5);
vec3 H = texture(Source, t4.yw).rgb; mat4x3 g5 = mat4x3(G5, I4, C1, A0);
vec3 I = texture(Source, t4.zw).rgb;
vec3 G5 = texture(Source, t5.xw).rgb; mat4x3 c1 = mat4x3(C1, A0, G5, I4);
vec3 H5 = texture(Source, t5.yw).rgb; mat4x3 g0 = mat4x3(G0, I5, C4, A1);
vec3 I5 = texture(Source, t5.zw).rgb; mat4x3 b1 = mat4x3(B1, D0, H5, F4);
mat4x3 d0 = mat4x3(D0, H5, F4, B1);
vec3 A0 = texture(Source, t6.xy).rgb; vec4 b_ = v2f * b;
vec3 D0 = texture(Source, t6.xz).rgb; vec4 c_ = v2f * c;
vec3 G0 = texture(Source, t6.xw).rgb; vec4 d_ = b_.yzwx;
vec4 e_ = v2f * e;
vec4 f_ = b_.wxyz;
vec4 g_ = c_.zwxy;
vec4 h_ = b_.zwxy;
vec4 i_ = c_.wxyz;
vec3 C4 = texture(Source, t7.xy).rgb; vec4 i4_ = v2f * i4;
vec3 F4 = texture(Source, t7.xz).rgb; vec4 i5_ = v2f * i5;
vec3 I4 = texture(Source, t7.xw).rgb; vec4 h5_ = v2f * h5;
vec4 f4_ = h5_.yzwx;
vec4 b = transpose(mat4x3(B, D, H, F)) * (params.XBR_Y_WEIGHT * yuv[0]); vec4 c4_ = i5_.yzwx;
vec4 c = transpose(mat4x3(C, A, G, I)) * (params.XBR_Y_WEIGHT * yuv[0]); vec4 g5_ = i4_.wxyz;
vec4 e = transpose(mat4x3(E, E, E, E)) * (params.XBR_Y_WEIGHT * yuv[0]);
vec4 d = b.yzwx;
vec4 f = b.wxyz;
vec4 g = c.zwxy;
vec4 h = b.zwxy;
vec4 i = c.wxyz;
vec4 i4 = transpose(mat4x3(I4, C1, A0, G5)) * (params.XBR_Y_WEIGHT*yuv[0]); vec4 c1_ = i4_.yzwx;
vec4 i5 = transpose(mat4x3(I5, C4, A1, G0)) * (params.XBR_Y_WEIGHT*yuv[0]); vec4 g0_ = i5_.wxyz;
vec4 h5 = transpose(mat4x3(H5, F4, B1, D0)) * (params.XBR_Y_WEIGHT*yuv[0]); vec4 b1_ = h5_.zwxy;
vec4 f4 = h5.yzwx; vec4 d0_ = h5_.wxyz;
vec4 c1 = i4.yzwx;
vec4 g0 = i5.wxyz;
vec4 b1 = h5.zwxy;
vec4 d0 = h5.wxyz;
vec4 Ao = vec4( 1.0, -1.0, -1.0, 1.0 );
vec4 Bo = vec4( 1.0, 1.0, -1.0,-1.0 );
vec4 Co = vec4( 1.5, 0.5, -0.5, 0.5 );
vec4 Ax = vec4( 1.0, -1.0, -1.0, 1.0 );
vec4 Bx = vec4( 0.5, 2.0, -0.5,-2.0 );
vec4 Cx = vec4( 1.0, 1.0, -0.5, 0.0 );
vec4 Ay = vec4( 1.0, -1.0, -1.0, 1.0 );
vec4 By = vec4( 2.0, 0.5, -2.0,-0.5 );
vec4 Cy = vec4( 2.0, 0.0, -1.0, 0.5 );
vec4 Az = vec4( 6.0, -2.0, -6.0, 2.0 );
vec4 Bz = vec4( 2.0, 6.0, -2.0, -6.0 );
vec4 Cz = vec4( 5.0, 3.0, -3.0, -1.0 );
vec4 Aw = vec4( 2.0, -6.0, -2.0, 6.0 );
vec4 Bw = vec4( 6.0, 2.0, -6.0,-2.0 );
vec4 Cw = vec4( 5.0, -1.0, -3.0, 3.0 );
// These inequations define the line below which interpolation occurs.
fx = ( Ao*fp.y + Bo*fp.x ); fx = ( Ao*fp.y + Bo*fp.x );
fx_left = (Ax*fp.y+Bx*fp.x); fx_l = ( Ax*fp.y + Bx*fp.x );
fx_up = (Ay*fp.y+By*fp.x); fx_u = ( Ay*fp.y + By*fp.x );
fx3_left= (Az*fp.y+Bz*fp.x); fx3_l = ( Az*fp.y + Bz*fp.x );
fx3_up = (Aw*fp.y+Bw*fp.x); fx3_u = ( Aw*fp.y + Bw*fp.x );
// It uses CORNER_C if none of the others are defined. irlv0 = diff(e_,f_) * diff(e_,h_);
if(params.corner_type == 1.0) irlv1 = irlv0;
{interp_restriction_lv1 = and(notEqual(e, f), notEqual(e, h));}
else if(params.corner_type == 2.0)
{interp_restriction_lv1 = and(and(notEqual(e,f) , notEqual(e,h)) ,
( or(or(and(and(or(and(not(eq(f,b)) , not(eq(h,d))) ,
eq(e,i)) , not(eq(f,i4))) , not(eq(h,i5))) , eq(e,g)) , eq(e,c)) ) );}
//commenting this one out because something got broken
/*else if(params.corner_type == 6.0)
{interp_restriction_lv1 = and(and(and(notEqual(e,f) , notEqual(e,h)) ,
( or(or(and(and(or(and(not(eq(f,b)) , not(eq(h,d))) ,
eq(e,i)) , not(eq(f,i4))) , not(eq(h,i5))) , eq(e,g)) ,
eq(e,c)) )) , (and(or(or(or(or(and(notEqual(f,f4) , notEqual(f,i)) ,
and(notEqual(h,h5) , notEqual(h,i))) , notEqual(h,g)) , notEqual(f,c)) ,
eq(b,c1)) , eq(d,g0))));} */
else
{interp_restriction_lv1 = and(and(notEqual(e, f), notEqual(e, h)),
or(or(and(not(eq(f,b)), not(eq(f,c))),
and(not(eq(h,d)), not(eq(h,g)))),
or(and(eq(e,i), or(and(not(eq(f,f4)), not(eq(f,i4))),
and(not(eq(h,h5)), not(eq(h,i5))))),
or(eq(e,g), eq(e,c)))));}
interp_restriction_lv2_left = and(notEqual(e, g), notEqual(d, g)); #ifdef CORNER_B
interp_restriction_lv2_up = and(notEqual(e, c), notEqual(b, c)); irlv1 = saturate(irlv0 * ( neq(f,b) * neq(h,d) + eq(e,i) * neq(f,i4) * neq(h,i5) + eq(e,g) + eq(e,c) ) );
interp_restriction_lv3_left = and(eq2(g,g0), not(eq2(d0,g0))); #endif
interp_restriction_lv3_up = and(eq2(c,c1), not(eq2(b1,c1))); #ifdef CORNER_C
irlv1 = saturate(irlv0 * ( neq(f,b) * neq(f,c) + neq(h,d) * neq(h,g) + eq(e,i) * (neq(f,f4) * neq(f,i4) + neq(h,h5) * neq(h,i5)) + eq(e,g) + eq(e,c)) );
#endif
vec4 fx45 = smoothstep(Co - delta, Co + delta, fx); irlv2l = diff(e_,g_) * diff( d_, g_);
vec4 fx30 = smoothstep(Cx - delta, Cx + delta, fx_left); irlv2u = diff(e_,c_) * diff( b_, c_);
vec4 fx60 = smoothstep(Cy - delta, Cy + delta, fx_up); irlv3l = eq2(g,g0) * diff(d0_,g0_);
vec4 fx15 = smoothstep(Cz - delta, Cz + delta, fx3_left); irlv3u = eq2(c,c1) * diff(b1_,c1_);
vec4 fx75 = smoothstep(Cw - delta, Cw + delta, fx3_up);
edr = and(lessThan(weighted_distance( e, c, g, i, h5, f4, h, f), weighted_distance( h, d, i5, f, i4, b, e, i)), interp_restriction_lv1); if (XBR_BLENDING == 1.0) {
edr_left = and(lessThanEqual((params.XBR_LV2_COEFFICIENT*df(f,g)), df(h,c)), interp_restriction_lv2_left); vec4 delta = vec4(aa_factor);
edr_up = and(greaterThanEqual(df(f,g), (params.XBR_LV2_COEFFICIENT*df(h,c))), interp_restriction_lv2_up); vec4 deltaL = vec4(0.5, 1.0, 0.5, 1.0) * aa_factor;
edr3_left = interp_restriction_lv3_left; vec4 deltaU = deltaL.yxwz;
edr3_up = interp_restriction_lv3_up;
nc45 = and(edr, bvec4(fx45)); fx45i = saturate( 0.5 + (fx - Co - Ci) / delta );
nc30 = and(edr, and(edr_left, bvec4(fx30))); fx45 = saturate( 0.5 + (fx - Co ) / delta );
nc60 = and(edr, and(edr_up, bvec4(fx60))); fx30 = saturate( 0.5 + (fx_l - Cx ) / deltaL );
nc15 = and(and(edr, edr_left), and(edr3_left, bvec4(fx15))); fx60 = saturate( 0.5 + (fx_u - Cy ) / deltaU );
nc75 = and(and(edr, edr_up), and(edr3_up, bvec4(fx75))); }
else {
fx45i = LT( Co + Ci, fx );
fx45 = LT( Co, fx );
fx30 = LT( Cx, fx_l );
fx60 = LT( Cy, fx_u );
}
px = lessThanEqual(df(e, f), df(e, h)); fx15 = LT( Cz, fx3_l ); // Can't do AA on lv3, yet! TO FIX LATER!
fx75 = LT( Cw, fx3_u );
nc = bvec4(nc75.x || nc15.x || nc30.x || nc60.x || nc45.x, nc75.y || nc15.y || nc30.y || nc60.y || nc45.y, nc75.z || nc15.z || nc30.z || nc60.z || nc45.z, nc75.w || nc15.w || nc30.w || nc60.w || nc45.w); vec4 wd1 = weighted_distance( e, c, g, i, h5, f4, h, f);
vec4 wd2 = weighted_distance( h, d, i5, f, i4, b, e, i);
vec4 final45 = vec4(nc45) * fx45; vec4 d_fg = dist4(f, g);
vec4 final30 = vec4(nc30) * fx30; vec4 d_hc = dist4(h, c);
vec4 final60 = vec4(nc60) * fx60;
vec4 final15 = vec4(nc15) * fx15;
vec4 final75 = vec4(nc75) * fx75;
vec4 maximo = max(max(max(final15, final75),max(final30, final60)), final45); edri = LTE( wd1, wd2 ) * irlv0;
edr = LT( wd1, wd2 ) * irlv1 * NOT(edri.yzwx * edri.wxyz);
edr_l = LTE( lv2_cf * d_fg, d_hc ) * irlv2l * edr * (NOT(edri.yzwx) * eq(e, c));
edr_u = LTE( lv2_cf * d_hc, d_fg ) * irlv2u * edr * (NOT(edri.wxyz) * eq(e, g));
edr3_l = irlv3l * edr_l;
edr3_u = irlv3u * edr_u;
if (nc.x) {pix1 = px.x ? F : H; blend1 = maximo.x;} fx45i = edri * fx45i;
else if (nc.y) {pix1 = px.y ? B : F; blend1 = maximo.y;} fx45 = edr * fx45;
else if (nc.z) {pix1 = px.z ? D : B; blend1 = maximo.z;} fx30 = edr_l * fx30;
else if (nc.w) {pix1 = px.w ? H : D; blend1 = maximo.w;} fx60 = edr_u * fx60;
fx15 = edr3_l * fx15 * eq(e,c4); // Needs further tests!
fx75 = edr3_u * fx75 * eq(e,g5);
if (nc.w) {pix2 = px.w ? H : D; blend2 = maximo.w;} px = LTE(dist4(e,f), dist4(e,h));
else if (nc.z) {pix2 = px.z ? D : B; blend2 = maximo.z;}
else if (nc.y) {pix2 = px.y ? B : F; blend2 = maximo.y;}
else if (nc.x) {pix2 = px.x ? F : H; blend2 = maximo.x;}
res1 = mix(E, pix1, blend1); vec4 maximos = max(max(max(fx15, fx30), max(fx60, fx75)), max(fx45, fx45i));
res2 = mix(E, pix2, blend2);
vec3 res = mix(res1, res2, step(c_df(E, res1), c_df(E, res2))); res1 = mix(E, mix(H, F, px.x), maximos.x);
res2 = mix(E, mix(B, D, px.z), maximos.z);
vec3 res1a = mix(res1, res2, step(dist(E, res1), dist(E, res2)));
res1 = mix(E, mix(F, B, px.y), maximos.y);
res2 = mix(E, mix(D, H, px.w), maximos.w);
vec3 res1b = mix(res1, res2, step(dist(E, res1), dist(E, res2)));
vec3 res = mix(res1a, res1b, step(dist(E, res1a), dist(E, res1b)));
FragColor = vec4(res, 1.0); FragColor = vec4(res, 1.0);
} }

4
xbr/xbr-lv1.slangp Normal file
View file

@ -0,0 +1,4 @@
shaders = 1
shader0 = "shaders/xbr-lv1.slang"
filter_linear0 = false

View file

@ -0,0 +1,10 @@
shaders = "2"
shader0 = shaders/xbr-lv2-multipass/xbr-lv2-pass0.slang
scale_type0 = "source"
scale0 = "1.000000"
shader1 = shaders/xbr-lv2-multipass/xbr-lv2-pass1.slang
filter_linear0 = "false"
filter_linear1 = "false"

20
xbr/xbr-lv3-9x.slangp Normal file
View file

@ -0,0 +1,20 @@
shaders = 3
shader0 = shaders/xbr-lv3.slang
filter_linear0 = false
scale_type0 = "source"
scale0 = "3.000000"
shader1 = shaders/xbr-lv3.slang
filter_linear1 = false
scale_type1 = "source"
scale1 = "3.000000"
shader2 = "shaders/support/b-spline.slang"
filter_linear2 = false
parameters = "XBR_BLENDING"
XBR_BLENDING = "0.0"

View file

@ -1,4 +1,10 @@
shaders = 1 shaders = 2
shader0 = "shaders/xbr-lv3.slang" shader0 = shaders/xbr-lv3.slang
filter_linear0 = false filter_linear0 = false
scale_type0 = "source"
scale0 = "3.000000"
shader1 = "shaders/support/b-spline.slang"
filter_linear1 = false