mirror of
https://github.com/italicsjenga/slang-shaders.git
synced 2024-11-22 15:51:30 +11:00
update scalefx shaders
This commit is contained in:
parent
8243af2064
commit
27b36311a1
31
scalefx/scalefx-hybrid.slangp
Normal file
31
scalefx/scalefx-hybrid.slangp
Normal file
|
@ -0,0 +1,31 @@
|
|||
shaders = 5
|
||||
|
||||
shader0 = shaders\scalefx-pass0.slang
|
||||
filter_linear0 = false
|
||||
scale_type0 = source
|
||||
scale0 = 1.0
|
||||
float_framebuffer0 = true
|
||||
|
||||
shader1 = shaders\scalefx-pass1.slang
|
||||
filter_linear1 = false
|
||||
scale_type1 = source
|
||||
scale1 = 1.0
|
||||
float_framebuffer1 = true
|
||||
|
||||
shader2 = shaders\scalefx-pass2.slang
|
||||
filter_linear2 = false
|
||||
scale_type2 = source
|
||||
scale2 = 1.0
|
||||
|
||||
shader3 = shaders\scalefx-pass3.slang
|
||||
filter_linear3 = false
|
||||
scale_type3 = source
|
||||
scale3 = 1.0
|
||||
|
||||
shader4 = shaders\scalefx-pass4-hybrid.slang
|
||||
filter_linear4 = false
|
||||
scale_type4 = source
|
||||
scale4 = 3.0
|
||||
|
||||
parameters = "SFX_SAA"
|
||||
SFX_SAA = "0.0"
|
|
@ -1,21 +1,28 @@
|
|||
shaders = 4
|
||||
shaders = 5
|
||||
|
||||
shader0 = shaders/scalefx-pass0.slang
|
||||
shader0 = shaders\scalefx-pass0.slang
|
||||
filter_linear0 = false
|
||||
scale_type0 = source
|
||||
scale0 = 1.0
|
||||
float_framebuffer0 = true
|
||||
|
||||
shader1 = shaders/scalefx-pass1.slang
|
||||
shader1 = shaders\scalefx-pass1.slang
|
||||
filter_linear1 = false
|
||||
scale_type1 = source
|
||||
scale1 = 1.0
|
||||
float_framebuffer1 = true
|
||||
|
||||
shader2 = shaders/scalefx-pass2.slang
|
||||
shader2 = shaders\scalefx-pass2.slang
|
||||
filter_linear2 = false
|
||||
scale_type2 = source
|
||||
scale2 = 1.0
|
||||
|
||||
shader3 = shaders/scalefx-pass3.slang
|
||||
shader3 = shaders\scalefx-pass3.slang
|
||||
filter_linear3 = false
|
||||
scale_type3 = source
|
||||
scale3 = 3.0
|
||||
scale3 = 1.0
|
||||
|
||||
shader4 = shaders\scalefx-pass4.slang
|
||||
filter_linear4 = false
|
||||
scale_type4 = source
|
||||
scale4 = 3.0
|
||||
|
|
49
scalefx/shaders/old/scalefx-9x-old.slangp
Normal file
49
scalefx/shaders/old/scalefx-9x-old.slangp
Normal file
|
@ -0,0 +1,49 @@
|
|||
shaders = 8
|
||||
|
||||
shader0 = scalefx-pass0.slang
|
||||
filter_linear0 = false
|
||||
scale_type0 = source
|
||||
scale0 = 1.0
|
||||
alias0 = sfxp0
|
||||
|
||||
shader1 = scalefx-pass1.slang
|
||||
filter_linear1 = false
|
||||
scale_type1 = source
|
||||
scale1 = 1.0
|
||||
alias1 = sfxp1
|
||||
|
||||
shader2 = scalefx-pass2.slang
|
||||
filter_linear2 = false
|
||||
scale_type2 = source
|
||||
scale2 = 1.0
|
||||
alias2 = sfxp2
|
||||
|
||||
shader3 = scalefx-pass3.slang
|
||||
filter_linear3 = false
|
||||
scale_type3 = source
|
||||
scale3 = 3.0
|
||||
alias3 = sfxp3
|
||||
|
||||
shader4 = scalefx-pass0.slang
|
||||
filter_linear4 = false
|
||||
scale_type4 = source
|
||||
scale4 = 1.0
|
||||
alias4 = sfxp4
|
||||
|
||||
shader5 = scalefx-pass1.slang
|
||||
filter_linear5 = false
|
||||
scale_type5 = source
|
||||
scale5 = 1.0
|
||||
alias5 = sfxp5
|
||||
|
||||
shader6 = scalefx-pass2.slang
|
||||
filter_linear6 = false
|
||||
scale_type6 = source
|
||||
scale6 = 1.0
|
||||
alias6 = sfxp6
|
||||
|
||||
shader7 = scalefx-pass7.slang
|
||||
filter_linear7 = false
|
||||
scale_type7 = source
|
||||
scale7 = 3.0
|
||||
alias7 = sfxp7
|
21
scalefx/shaders/old/scalefx-old.slangp
Normal file
21
scalefx/shaders/old/scalefx-old.slangp
Normal file
|
@ -0,0 +1,21 @@
|
|||
shaders = 4
|
||||
|
||||
shader0 = scalefx-pass0.slang
|
||||
filter_linear0 = false
|
||||
scale_type0 = source
|
||||
scale0 = 1.0
|
||||
|
||||
shader1 = scalefx-pass1.slang
|
||||
filter_linear1 = false
|
||||
scale_type1 = source
|
||||
scale1 = 1.0
|
||||
|
||||
shader2 = scalefx-pass2.slang
|
||||
filter_linear2 = false
|
||||
scale_type2 = source
|
||||
scale2 = 1.0
|
||||
|
||||
shader3 = scalefx-pass3.slang
|
||||
filter_linear3 = false
|
||||
scale_type3 = source
|
||||
scale3 = 3.0
|
104
scalefx/shaders/old/scalefx-pass0.slang
Normal file
104
scalefx/shaders/old/scalefx-pass0.slang
Normal file
|
@ -0,0 +1,104 @@
|
|||
#version 450
|
||||
|
||||
/*
|
||||
ScaleFX - Pass 0
|
||||
by Sp00kyFox, 2016-03-30
|
||||
|
||||
Filter: Nearest
|
||||
Scale: 1x
|
||||
|
||||
ScaleFX is an edge interpolation algorithm specialized in pixel art. It was
|
||||
originally intended as an improvement upon Scale3x but became a new filter in
|
||||
its own right.
|
||||
ScaleFX interpolates edges up to level 6 and makes smooth transitions between
|
||||
different slopes. The filtered picture will only consist of colours present
|
||||
in the original.
|
||||
|
||||
Pass 0 prepares metric data for the next pass.
|
||||
|
||||
|
||||
|
||||
Copyright (c) 2016 Sp00kyFox - ScaleFX@web.de
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#pragma name sfxp0
|
||||
|
||||
|
||||
// Reference: http://www.compuphase.com/cmetric.htm
|
||||
float eq(vec3 A, vec3 B)
|
||||
{
|
||||
float r = 0.5 * (A.r + B.r);
|
||||
vec3 d = A - B;
|
||||
vec3 c = vec3(2 + r, 4, 3 - r);
|
||||
|
||||
return 1 - sqrt(dot(c*d, d)) / 3;
|
||||
}
|
||||
|
||||
|
||||
layout(set = 0, binding = 0, std140) uniform UBO
|
||||
{
|
||||
mat4 MVP;
|
||||
vec4 SourceSize;
|
||||
};
|
||||
|
||||
|
||||
#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 = MVP * Position;
|
||||
vTexCoord = TexCoord;
|
||||
}
|
||||
|
||||
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(binding = 1) uniform sampler2D Source;
|
||||
|
||||
|
||||
#define TEX(x, y) textureOffset(Source, vTexCoord, ivec2(x, y))
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
/* grid metric
|
||||
|
||||
A B C x y z
|
||||
E F o w
|
||||
*/
|
||||
|
||||
|
||||
// read texels
|
||||
vec3 A = TEX(-1,-1).rgb;
|
||||
vec3 B = TEX( 0,-1).rgb;
|
||||
vec3 C = TEX( 1,-1).rgb;
|
||||
vec3 E = TEX( 0, 0).rgb;
|
||||
vec3 F = TEX( 1, 0).rgb;
|
||||
|
||||
// output
|
||||
FragColor = vec4(eq(E,A), eq(E,B), eq(E,C), eq(E,F));
|
||||
}
|
199
scalefx/shaders/old/scalefx-pass1.slang
Normal file
199
scalefx/shaders/old/scalefx-pass1.slang
Normal file
|
@ -0,0 +1,199 @@
|
|||
#version 450
|
||||
|
||||
/*
|
||||
ScaleFX - Pass 1
|
||||
by Sp00kyFox, 2016-03-30
|
||||
|
||||
Filter: Nearest
|
||||
Scale: 1x
|
||||
|
||||
ScaleFX is an edge interpolation algorithm specialized in pixel art. It was
|
||||
originally intended as an improvement upon Scale3x but became a new filter in
|
||||
its own right.
|
||||
ScaleFX interpolates edges up to level 6 and makes smooth transitions between
|
||||
different slopes. The filtered picture will only consist of colours present
|
||||
in the original.
|
||||
|
||||
Pass 1 resolves ambiguous configurations of corner candidates at pixel junctions.
|
||||
|
||||
|
||||
|
||||
Copyright (c) 2016 Sp00kyFox - ScaleFX@web.de
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#pragma name sfxp1
|
||||
#pragma parameter SFX_CLR "ScaleFX Color Thresh" 0.35 0.0 1.00 0.01
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform float SFX_CLR;
|
||||
#else
|
||||
#define SFX_CLR 0.35
|
||||
#endif
|
||||
|
||||
const float THR = 1.0 - SFX_CLR;
|
||||
|
||||
|
||||
layout(set = 0, binding = 0, std140) uniform UBO
|
||||
{
|
||||
mat4 MVP;
|
||||
vec4 SourceSize;
|
||||
};
|
||||
|
||||
|
||||
#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 = MVP * Position;
|
||||
vTexCoord = TexCoord;
|
||||
}
|
||||
|
||||
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(binding = 1) uniform sampler2D Source;
|
||||
|
||||
|
||||
#define LE(x, y) (1.0 - step(y, x))
|
||||
#define GE(x, y) (1.0 - step(x, y))
|
||||
#define LEQ(x, y) step(x, y)
|
||||
#define GEQ(x, y) step(y, x)
|
||||
#define NOT(x) (1.0 - (x))
|
||||
|
||||
|
||||
// corner strength
|
||||
vec4 str(vec4 crn, vec4 ort){
|
||||
//return (crn > THR) ? max(2.0*crn - (ort + ort.wxyz), 0.0) : 0.0;
|
||||
return GE(crn, vec4(THR)) * max(2.0*crn - (ort + ort.wxyz), vec4(0.0));
|
||||
}
|
||||
|
||||
// corner dominance at junctions
|
||||
vec4 dom(vec3 strx, vec3 stry, vec3 strz, vec3 strw){
|
||||
vec4 res;
|
||||
res.x = max(2.0*strx.y - (strx.x + strx.z), 0.0);
|
||||
res.y = max(2.0*stry.y - (stry.x + stry.z), 0.0);
|
||||
res.z = max(2.0*strz.y - (strz.x + strz.z), 0.0);
|
||||
res.w = max(2.0*strw.y - (strw.x + strw.z), 0.0);
|
||||
return res;
|
||||
}
|
||||
|
||||
// necessary but not sufficient junction condition for orthogonal edges
|
||||
float clear(vec2 crn, vec4 ort){
|
||||
//return all(crn.xyxy <= THR || crn.xyxy <= ort || crn.xyxy <= ort.wxyz);
|
||||
vec4 res = LEQ(crn.xyxy, vec4(THR)) + LEQ(crn.xyxy, ort) + LEQ(crn.xyxy, ort.wxyz);
|
||||
return min(res.x * res.y * res.z * res.w, 1.0);
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
/* grid metric pattern
|
||||
|
||||
M A B C P x y z x y
|
||||
N D E F Q o w w z
|
||||
O G H I R
|
||||
J K L
|
||||
*/
|
||||
|
||||
|
||||
#define TEX(x, y) textureOffset(Source, vTexCoord, ivec2(x, y))
|
||||
|
||||
|
||||
// metric data
|
||||
vec4 A = TEX(-1,-1), B = TEX( 0,-1), C = TEX( 1,-1);
|
||||
vec4 D = TEX(-1, 0), E = TEX( 0, 0), F = TEX( 1, 0);
|
||||
vec4 G = TEX(-1, 1), H = TEX( 0, 1), I = TEX( 1, 1);
|
||||
vec4 J = TEX(-1, 2), K = TEX( 0, 2), L = TEX( 1, 2);
|
||||
vec4 M = TEX(-2,-1), N = TEX(-2, 0), O = TEX(-2, 1);
|
||||
vec4 P = TEX( 2,-1), Q = TEX( 2, 0), R = TEX( 2, 1);
|
||||
|
||||
|
||||
// corner strength
|
||||
vec4 As = str(vec4(M.z, B.x, D.zx), vec4(A.yw, D.y, M.w));
|
||||
vec4 Bs = str(vec4(A.z, C.x, E.zx), vec4(B.yw, E.y, A.w));
|
||||
vec4 Cs = str(vec4(B.z, P.x, F.zx), vec4(C.yw, F.y, B.w));
|
||||
vec4 Ds = str(vec4(N.z, E.x, G.zx), vec4(D.yw, G.y, N.w));
|
||||
vec4 Es = str(vec4(D.z, F.x, H.zx), vec4(E.yw, H.y, D.w));
|
||||
vec4 Fs = str(vec4(E.z, Q.x, I.zx), vec4(F.yw, I.y, E.w));
|
||||
vec4 Gs = str(vec4(O.z, H.x, J.zx), vec4(G.yw, J.y, O.w));
|
||||
vec4 Hs = str(vec4(G.z, I.x, K.zx), vec4(H.yw, K.y, G.w));
|
||||
vec4 Is = str(vec4(H.z, R.x, L.zx), vec4(I.yw, L.y, H.w));
|
||||
|
||||
// strength & dominance junctions
|
||||
vec4 jSx = vec4(As.z, Bs.w, Es.x, Ds.y), jDx = dom(As.yzw, Bs.zwx, Es.wxy, Ds.xyz);
|
||||
vec4 jSy = vec4(Bs.z, Cs.w, Fs.x, Es.y), jDy = dom(Bs.yzw, Cs.zwx, Fs.wxy, Es.xyz);
|
||||
vec4 jSz = vec4(Es.z, Fs.w, Is.x, Hs.y), jDz = dom(Es.yzw, Fs.zwx, Is.wxy, Hs.xyz);
|
||||
vec4 jSw = vec4(Ds.z, Es.w, Hs.x, Gs.y), jDw = dom(Ds.yzw, Es.zwx, Hs.wxy, Gs.xyz);
|
||||
|
||||
|
||||
// majority vote for ambiguous dominance junctions
|
||||
//bvec4 jx = jDx != 0.0 && jDx + jDx.zwxy > jDx.yzwx + jDx.wxyz;
|
||||
//bvec4 jy = jDy != 0.0 && jDy + jDy.zwxy > jDy.yzwx + jDy.wxyz;
|
||||
//bvec4 jz = jDz != 0.0 && jDz + jDz.zwxy > jDz.yzwx + jDz.wxyz;
|
||||
//bvec4 jw = jDw != 0.0 && jDw + jDw.zwxy > jDw.yzwx + jDw.wxyz;
|
||||
|
||||
vec4 jx = GE(jDx, vec4(0.0)) * GE(jDx + jDx.zwxy, jDx.yzwx + jDx.wxyz);
|
||||
vec4 jy = GE(jDy, vec4(0.0)) * GE(jDy + jDy.zwxy, jDy.yzwx + jDy.wxyz);
|
||||
vec4 jz = GE(jDz, vec4(0.0)) * GE(jDz + jDz.zwxy, jDz.yzwx + jDz.wxyz);
|
||||
vec4 jw = GE(jDw, vec4(0.0)) * GE(jDw + jDw.zwxy, jDw.yzwx + jDw.wxyz);
|
||||
|
||||
// inject strength without creating new contradictions
|
||||
//bvec4 res;
|
||||
//res.x = jx.z || !(jx.y || jx.w) && (jSx.z != 0.0 && (jx.x || jSx.x + jSx.z > jSx.y + jSx.w));
|
||||
//res.y = jy.w || !(jy.z || jy.x) && (jSy.w != 0.0 && (jy.y || jSy.y + jSy.w > jSy.x + jSy.z));
|
||||
//res.z = jz.x || !(jz.w || jz.y) && (jSz.x != 0.0 && (jz.z || jSz.x + jSz.z > jSz.y + jSz.w));
|
||||
//res.w = jw.y || !(jw.x || jw.z) && (jSw.y != 0.0 && (jw.w || jSw.y + jSw.w > jSw.x + jSw.z));
|
||||
|
||||
vec4 res;
|
||||
res.x = min(jx.z + (NOT(jx.y) * NOT(jx.w)) * (GE(jSx.z, 0.0) * (jx.x + GE(jSx.x + jSx.z, jSx.y + jSx.w))), 1.0);
|
||||
res.y = min(jy.w + (NOT(jy.z) * NOT(jy.x)) * (GE(jSy.w, 0.0) * (jy.y + GE(jSy.y + jSy.w, jSy.x + jSy.z))), 1.0);
|
||||
res.z = min(jz.x + (NOT(jz.w) * NOT(jz.y)) * (GE(jSz.x, 0.0) * (jz.z + GE(jSz.x + jSz.z, jSz.y + jSz.w))), 1.0);
|
||||
res.w = min(jw.y + (NOT(jw.x) * NOT(jw.z)) * (GE(jSw.y, 0.0) * (jw.w + GE(jSw.y + jSw.w, jSw.x + jSw.z))), 1.0);
|
||||
|
||||
|
||||
// single pixel & end of line detection
|
||||
//res = res && (bvec4(jx.z, jy.w, jz.x, jw.y) || !(res.wxyz && res.yzwx));
|
||||
res = min(res * (vec4(jx.z, jy.w, jz.x, jw.y) + NOT(res.wxyz * res.yzwx)), vec4(1.0));
|
||||
|
||||
|
||||
// output
|
||||
|
||||
vec4 clr;
|
||||
clr.x = clear(vec2(D.z, E.x), vec4(A.w, E.y, D.wy));
|
||||
clr.y = clear(vec2(E.z, F.x), vec4(B.w, F.y, E.wy));
|
||||
clr.z = clear(vec2(H.z, I.x), vec4(E.w, I.y, H.wy));
|
||||
clr.w = clear(vec2(G.z, H.x), vec4(D.w, H.y, G.wy));
|
||||
|
||||
vec4 low = max(vec4(E.yw, H.y, D.w), vec4(THR));
|
||||
|
||||
vec4 hori = vec4(low.x < max(D.w, A.w), low.x < max(E.w, B.w), low.z < max(E.w, H.w), low.z < max(D.w, G.w)) * clr; // horizontal edges
|
||||
vec4 vert = vec4(low.w < max(E.y, D.y), low.y < max(E.y, F.y), low.y < max(H.y, I.y), low.w < max(H.y, G.y)) * clr; // vertical edges
|
||||
vec4 or = vec4(A.w < D.y, B.w <= F.y, H.w < I.y, G.w <= G.y); // orientation
|
||||
|
||||
FragColor = (res + 2.0 * hori + 4.0 * vert + 8.0 * or) / 15.0;
|
||||
}
|
171
scalefx/shaders/old/scalefx-pass2.slang
Normal file
171
scalefx/shaders/old/scalefx-pass2.slang
Normal file
|
@ -0,0 +1,171 @@
|
|||
#version 450
|
||||
|
||||
/*
|
||||
ScaleFX - Pass 2
|
||||
by Sp00kyFox, 2016-03-30
|
||||
|
||||
Filter: Nearest
|
||||
Scale: 1x
|
||||
|
||||
ScaleFX is an edge interpolation algorithm specialized in pixel art. It was
|
||||
originally intended as an improvement upon Scale3x but became a new filter in
|
||||
its own right.
|
||||
ScaleFX interpolates edges up to level 6 and makes smooth transitions between
|
||||
different slopes. The filtered picture will only consist of colours present
|
||||
in the original.
|
||||
|
||||
Pass 2 determines which edge level is present and prepares tags for subpixel
|
||||
output in the final pass.
|
||||
|
||||
|
||||
|
||||
Copyright (c) 2016 Sp00kyFox - ScaleFX@web.de
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#pragma name sfxp2
|
||||
|
||||
|
||||
layout(set = 0, binding = 0, std140) uniform UBO
|
||||
{
|
||||
mat4 MVP;
|
||||
vec4 SourceSize;
|
||||
};
|
||||
|
||||
|
||||
#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 = MVP * Position;
|
||||
vTexCoord = TexCoord;
|
||||
}
|
||||
|
||||
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(binding = 1) uniform sampler2D Source;
|
||||
|
||||
|
||||
// extract first bool4 from float4 - corners
|
||||
bvec4 loadCorn(vec4 x){
|
||||
return bvec4(floor(mod(x*15 + 0.5, 2.0)));
|
||||
}
|
||||
|
||||
// extract second bool4 from float4 - horizontal edges
|
||||
bvec4 loadHori(vec4 x){
|
||||
return bvec4(floor(mod(x*7.5 + 0.25, 2.0)));
|
||||
}
|
||||
|
||||
// extract third bool4 from float4 - vertical edges
|
||||
bvec4 loadVert(vec4 x){
|
||||
return bvec4(floor(mod(x*3.75 + 0.125, 2.0)));
|
||||
}
|
||||
|
||||
// extract fourth bool4 from float4 - orientation
|
||||
bvec4 loadOr(vec4 x){
|
||||
return bvec4(floor(mod(x*1.875 + 0.0625, 2.0)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
/* grid corners mids
|
||||
|
||||
B x y x
|
||||
D E F w y
|
||||
H w z z
|
||||
*/
|
||||
|
||||
#define TEX(x, y) textureOffset(Source, vTexCoord, ivec2(x, y))
|
||||
|
||||
// read data
|
||||
vec4 E = TEX( 0, 0);
|
||||
vec4 D = TEX(-1, 0), D0 = TEX(-2, 0), D1 = TEX(-3, 0);
|
||||
vec4 F = TEX( 1, 0), F0 = TEX( 2, 0), F1 = TEX( 3, 0);
|
||||
vec4 B = TEX( 0,-1), B0 = TEX( 0,-2), B1 = TEX( 0,-3);
|
||||
vec4 H = TEX( 0, 1), H0 = TEX( 0, 2), H1 = TEX( 0, 3);
|
||||
|
||||
// extract data
|
||||
bvec4 Ec = loadCorn(E), Eh = loadHori(E), Ev = loadVert(E), Eo = loadOr(E);
|
||||
bvec4 Dc = loadCorn(D), Dh = loadHori(D), Do = loadOr(D), D0c = loadCorn(D0), D0h = loadHori(D0), D1h = loadHori(D1);
|
||||
bvec4 Fc = loadCorn(F), Fh = loadHori(F), Fo = loadOr(F), F0c = loadCorn(F0), F0h = loadHori(F0), F1h = loadHori(F1);
|
||||
bvec4 Bc = loadCorn(B), Bv = loadVert(B), Bo = loadOr(B), B0c = loadCorn(B0), B0v = loadVert(B0), B1v = loadVert(B1);
|
||||
bvec4 Hc = loadCorn(H), Hv = loadVert(H), Ho = loadOr(H), H0c = loadCorn(H0), H0v = loadVert(H0), H1v = loadVert(H1);
|
||||
|
||||
|
||||
// lvl2 mid (left, right / up, down)
|
||||
bvec2 lvl2x = bvec2((Ec.x && Eh.y) && Dc.z, (Ec.y && Eh.x) && Fc.w);
|
||||
bvec2 lvl2y = bvec2((Ec.y && Ev.z) && Bc.w, (Ec.z && Ev.y) && Hc.x);
|
||||
bvec2 lvl2z = bvec2((Ec.w && Eh.z) && Dc.y, (Ec.z && Eh.w) && Fc.x);
|
||||
bvec2 lvl2w = bvec2((Ec.x && Ev.w) && Bc.z, (Ec.w && Ev.x) && Hc.y);
|
||||
|
||||
// lvl3 corners (hori, vert)
|
||||
bvec2 lvl3x = bvec2(lvl2x.y && (Dh.y && Dh.x) && Fh.z, lvl2w.y && (Bv.w && Bv.x) && Hv.z);
|
||||
bvec2 lvl3y = bvec2(lvl2x.x && (Fh.x && Fh.y) && Dh.w, lvl2y.y && (Bv.z && Bv.y) && Hv.w);
|
||||
bvec2 lvl3z = bvec2(lvl2z.x && (Fh.w && Fh.z) && Dh.x, lvl2y.x && (Hv.y && Hv.z) && Bv.x);
|
||||
bvec2 lvl3w = bvec2(lvl2z.y && (Dh.z && Dh.w) && Fh.y, lvl2w.x && (Hv.x && Hv.w) && Bv.y);
|
||||
|
||||
// lvl4 corners (hori, vert)
|
||||
bvec2 lvl4x = bvec2((Dc.x && Dh.y && Eh.x && Eh.y && Fh.x && Fh.y) && (D0c.z && D0h.w), (Bc.x && Bv.w && Ev.x && Ev.w && Hv.x && Hv.w) && (B0c.z && B0v.y));
|
||||
bvec2 lvl4y = bvec2((Fc.y && Fh.x && Eh.y && Eh.x && Dh.y && Dh.x) && (F0c.w && F0h.z), (Bc.y && Bv.z && Ev.y && Ev.z && Hv.y && Hv.z) && (B0c.w && B0v.x));
|
||||
bvec2 lvl4z = bvec2((Fc.z && Fh.w && Eh.z && Eh.w && Dh.z && Dh.w) && (F0c.x && F0h.y), (Hc.z && Hv.y && Ev.z && Ev.y && Bv.z && Bv.y) && (H0c.x && H0v.w));
|
||||
bvec2 lvl4w = bvec2((Dc.w && Dh.z && Eh.w && Eh.z && Fh.w && Fh.z) && (D0c.y && D0h.x), (Hc.w && Hv.x && Ev.w && Ev.x && Bv.w && Bv.x) && (H0c.y && H0v.z));
|
||||
|
||||
// lvl5 mid (left, right / up, down)
|
||||
bvec2 lvl5x = bvec2(lvl4x.x && (F0h.x && F0h.y) && (D1h.z && D1h.w), lvl4y.x && (D0h.y && D0h.x) && (F1h.w && F1h.z));
|
||||
bvec2 lvl5y = bvec2(lvl4y.y && (H0v.y && H0v.z) && (B1v.w && B1v.x), lvl4z.y && (B0v.z && B0v.y) && (H1v.x && H1v.w));
|
||||
bvec2 lvl5z = bvec2(lvl4w.x && (F0h.w && F0h.z) && (D1h.y && D1h.x), lvl4z.x && (D0h.z && D0h.w) && (F1h.x && F1h.y));
|
||||
bvec2 lvl5w = bvec2(lvl4x.y && (H0v.x && H0v.w) && (B1v.z && B1v.y), lvl4w.y && (B0v.w && B0v.x) && (H1v.y && H1v.z));
|
||||
|
||||
// lvl6 corners (hori, vert)
|
||||
bvec2 lvl6x = bvec2(lvl5x.y && (D1h.y && D1h.x), lvl5w.y && (B1v.w && B1v.x));
|
||||
bvec2 lvl6y = bvec2(lvl5x.x && (F1h.x && F1h.y), lvl5y.y && (B1v.z && B1v.y));
|
||||
bvec2 lvl6z = bvec2(lvl5z.x && (F1h.w && F1h.z), lvl5y.x && (H1v.y && H1v.z));
|
||||
bvec2 lvl6w = bvec2(lvl5z.y && (D1h.z && D1h.w), lvl5w.x && (H1v.x && H1v.w));
|
||||
|
||||
|
||||
// subpixels - 0 = E, 1 = D, 2 = D0, 3 = F, 4 = F0, 5 = B, 6 = B0, 7 = H, 8 = H0
|
||||
|
||||
vec4 crn;
|
||||
crn.x = (Ec.x && Eo.x || lvl3x.x && Eo.y || lvl4x.x && Do.x || lvl6x.x && Fo.y) ? 5 : (Ec.x || lvl3x.y && !Eo.w || lvl4x.y && !Bo.x || lvl6x.y && !Ho.w) ? 1 : lvl3x.x ? 3 : lvl3x.y ? 7 : lvl4x.x ? 2 : lvl4x.y ? 6 : lvl6x.x ? 4 : lvl6x.y ? 8 : 0;
|
||||
crn.y = (Ec.y && Eo.y || lvl3y.x && Eo.x || lvl4y.x && Fo.y || lvl6y.x && Do.x) ? 5 : (Ec.y || lvl3y.y && !Eo.z || lvl4y.y && !Bo.y || lvl6y.y && !Ho.z) ? 3 : lvl3y.x ? 1 : lvl3y.y ? 7 : lvl4y.x ? 4 : lvl4y.y ? 6 : lvl6y.x ? 2 : lvl6y.y ? 8 : 0;
|
||||
crn.z = (Ec.z && Eo.z || lvl3z.x && Eo.w || lvl4z.x && Fo.z || lvl6z.x && Do.w) ? 7 : (Ec.z || lvl3z.y && !Eo.y || lvl4z.y && !Ho.z || lvl6z.y && !Bo.y) ? 3 : lvl3z.x ? 1 : lvl3z.y ? 5 : lvl4z.x ? 4 : lvl4z.y ? 8 : lvl6z.x ? 2 : lvl6z.y ? 6 : 0;
|
||||
crn.w = (Ec.w && Eo.w || lvl3w.x && Eo.z || lvl4w.x && Do.w || lvl6w.x && Fo.z) ? 7 : (Ec.w || lvl3w.y && !Eo.x || lvl4w.y && !Ho.w || lvl6w.y && !Bo.x) ? 1 : lvl3w.x ? 3 : lvl3w.y ? 5 : lvl4w.x ? 2 : lvl4w.y ? 8 : lvl6w.x ? 4 : lvl6w.y ? 6 : 0;
|
||||
|
||||
vec4 mid;
|
||||
mid.x = (lvl2x.x && Eo.x || lvl2x.y && Eo.y || lvl5x.x && Do.x || lvl5x.y && Fo.y) ? 5 : lvl2x.x ? 1 : lvl2x.y ? 3 : lvl5x.x ? 2 : lvl5x.y ? 4 : (Ec.x && Dc.z && Ec.y && Fc.w) ? ( Eo.x ? Eo.y ? 5 : 3 : 1) : 0;
|
||||
mid.y = (lvl2y.x && !Eo.y || lvl2y.y && !Eo.z || lvl5y.x && !Bo.y || lvl5y.y && !Ho.z) ? 3 : lvl2y.x ? 5 : lvl2y.y ? 7 : lvl5y.x ? 6 : lvl5y.y ? 8 : (Ec.y && Bc.w && Ec.z && Hc.x) ? (!Eo.y ? !Eo.z ? 3 : 7 : 5) : 0;
|
||||
mid.z = (lvl2z.x && Eo.w || lvl2z.y && Eo.z || lvl5z.x && Do.w || lvl5z.y && Fo.z) ? 7 : lvl2z.x ? 1 : lvl2z.y ? 3 : lvl5z.x ? 2 : lvl5z.y ? 4 : (Ec.z && Fc.x && Ec.w && Dc.y) ? ( Eo.z ? Eo.w ? 7 : 1 : 3) : 0;
|
||||
mid.w = (lvl2w.x && !Eo.x || lvl2w.y && !Eo.w || lvl5w.x && !Bo.x || lvl5w.y && !Ho.w) ? 1 : lvl2w.x ? 5 : lvl2w.y ? 7 : lvl5w.x ? 6 : lvl5w.y ? 8 : (Ec.w && Hc.y && Ec.x && Bc.z) ? (!Eo.w ? !Eo.x ? 1 : 5 : 7) : 0;
|
||||
|
||||
|
||||
// ouput
|
||||
FragColor = (crn + 9 * mid) / 80;
|
||||
|
||||
}
|
114
scalefx/shaders/old/scalefx-pass3.slang
Normal file
114
scalefx/shaders/old/scalefx-pass3.slang
Normal file
|
@ -0,0 +1,114 @@
|
|||
#version 450
|
||||
|
||||
/*
|
||||
ScaleFX - Pass 3
|
||||
by Sp00kyFox, 2016-03-30
|
||||
|
||||
Filter: Nearest
|
||||
Scale: 3x
|
||||
|
||||
ScaleFX is an edge interpolation algorithm specialized in pixel art. It was
|
||||
originally intended as an improvement upon Scale3x but became a new filter in
|
||||
its own right.
|
||||
ScaleFX interpolates edges up to level 6 and makes smooth transitions between
|
||||
different slopes. The filtered picture will only consist of colours present
|
||||
in the original.
|
||||
|
||||
Pass 3 outputs subpixels based on previously calculated tags.
|
||||
|
||||
|
||||
|
||||
Copyright (c) 2016 Sp00kyFox - ScaleFX@web.de
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#pragma name sfxp3
|
||||
|
||||
|
||||
layout(set = 0, binding = 0, std140) uniform UBO
|
||||
{
|
||||
mat4 MVP;
|
||||
vec4 SourceSize;
|
||||
};
|
||||
|
||||
|
||||
#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 = MVP * Position;
|
||||
vTexCoord = TexCoord;
|
||||
}
|
||||
|
||||
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(binding = 1) uniform sampler2D Source;
|
||||
layout(binding = 2) uniform sampler2D Original;
|
||||
|
||||
|
||||
|
||||
// extract corners
|
||||
vec4 loadCrn(vec4 x){
|
||||
return floor(mod(x*80.0 + 0.5, 9.0));
|
||||
}
|
||||
|
||||
// extract mids
|
||||
vec4 loadMid(vec4 x){
|
||||
return floor(mod(x*8.888888 + 0.055555, 9.0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
/* grid corners mids
|
||||
|
||||
B x y x
|
||||
D E F w y
|
||||
H w z z
|
||||
*/
|
||||
|
||||
|
||||
// read data
|
||||
vec4 E = texture(Source, vTexCoord);
|
||||
|
||||
// extract data
|
||||
vec4 crn = loadCrn(E);
|
||||
vec4 mid = loadMid(E);
|
||||
|
||||
// determine subpixel
|
||||
vec2 fp = floor(3.0 * fract(vTexCoord*SourceSize.xy));
|
||||
float sp = fp.y == 0 ? (fp.x == 0 ? crn.x : fp.x == 1 ? mid.x : crn.y) : (fp.y == 1 ? (fp.x == 0 ? mid.w : fp.x == 1 ? 0 : mid.y) : (fp.x == 0 ? crn.w : fp.x == 1 ? mid.z : crn.z));
|
||||
|
||||
// output coordinate - 0 = E, 1 = D, 2 = D0, 3 = F, 4 = F0, 5 = B, 6 = B0, 7 = H, 8 = H0
|
||||
vec2 res = sp == 0 ? vec2(0,0) : sp == 1 ? vec2(-1,0) : sp == 2 ? vec2(-2,0) : sp == 3 ? vec2(1,0) : sp == 4 ? vec2(2,0) : sp == 5 ? vec2(0,-1) : sp == 6 ? vec2(0,-2) : sp == 7 ? vec2(0,1) : vec2(0,2);
|
||||
|
||||
// ouput
|
||||
FragColor = texture(Original, vTexCoord + 1/SourceSize.xy * res);
|
||||
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
/*
|
||||
ScaleFX - Pass 0
|
||||
by Sp00kyFox, 2016-03-30
|
||||
by Sp00kyFox, 2017-03-01
|
||||
|
||||
Filter: Nearest
|
||||
Scale: 1x
|
||||
|
@ -41,25 +41,15 @@ THE SOFTWARE.
|
|||
*/
|
||||
|
||||
|
||||
#pragma name sfxp0
|
||||
|
||||
|
||||
// Reference: http://www.compuphase.com/cmetric.htm
|
||||
float eq(vec3 A, vec3 B)
|
||||
layout(push_constant) uniform Push
|
||||
{
|
||||
float r = 0.5 * (A.r + B.r);
|
||||
vec3 d = A - B;
|
||||
vec3 c = vec3(2 + r, 4, 3 - r);
|
||||
|
||||
return 1 - sqrt(dot(c*d, d)) / 3;
|
||||
}
|
||||
|
||||
vec4 SourceSize;
|
||||
} params;
|
||||
|
||||
layout(set = 0, binding = 0, std140) uniform UBO
|
||||
{
|
||||
mat4 MVP;
|
||||
vec4 SourceSize;
|
||||
};
|
||||
} global;
|
||||
|
||||
|
||||
#pragma stage vertex
|
||||
|
@ -69,7 +59,7 @@ layout(location = 0) out vec2 vTexCoord;
|
|||
|
||||
void main()
|
||||
{
|
||||
gl_Position = MVP * Position;
|
||||
gl_Position = global.MVP * Position;
|
||||
vTexCoord = TexCoord;
|
||||
}
|
||||
|
||||
|
@ -80,7 +70,16 @@ layout(location = 0) out vec4 FragColor;
|
|||
layout(binding = 1) uniform sampler2D Source;
|
||||
|
||||
|
||||
#define TEX(x, y) textureOffset(Source, vTexCoord, ivec2(x, y))
|
||||
// Reference: http://www.compuphase.com/cmetric.htm
|
||||
float dist(vec3 A, vec3 B)
|
||||
{
|
||||
float r = 0.5 * (A.r + B.r);
|
||||
vec3 d = A - B;
|
||||
vec3 c = vec3(2 + r, 4, 3 - r);
|
||||
|
||||
return sqrt(dot(c*d, d)) / 3;
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
@ -92,13 +91,15 @@ void main()
|
|||
*/
|
||||
|
||||
|
||||
#define TEX(x, y) textureOffset(Source, vTexCoord, ivec2(x, y)).rgb
|
||||
|
||||
// read texels
|
||||
vec3 A = TEX(-1,-1).rgb;
|
||||
vec3 B = TEX( 0,-1).rgb;
|
||||
vec3 C = TEX( 1,-1).rgb;
|
||||
vec3 E = TEX( 0, 0).rgb;
|
||||
vec3 F = TEX( 1, 0).rgb;
|
||||
vec3 A = TEX(-1,-1);
|
||||
vec3 B = TEX( 0,-1);
|
||||
vec3 C = TEX( 1,-1);
|
||||
vec3 E = TEX( 0, 0);
|
||||
vec3 F = TEX( 1, 0);
|
||||
|
||||
// output
|
||||
FragColor = vec4(eq(E,A), eq(E,B), eq(E,C), eq(E,F));
|
||||
FragColor = vec4(dist(E,A), dist(E,B), dist(E,C), dist(E,F));
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
/*
|
||||
ScaleFX - Pass 1
|
||||
by Sp00kyFox, 2016-03-30
|
||||
by Sp00kyFox, 2017-03-01
|
||||
|
||||
Filter: Nearest
|
||||
Scale: 1x
|
||||
|
@ -14,7 +14,7 @@ ScaleFX interpolates edges up to level 6 and makes smooth transitions between
|
|||
different slopes. The filtered picture will only consist of colours present
|
||||
in the original.
|
||||
|
||||
Pass 1 resolves ambiguous configurations of corner candidates at pixel junctions.
|
||||
Pass 1 calculates the strength of interpolation candidates.
|
||||
|
||||
|
||||
|
||||
|
@ -41,23 +41,22 @@ THE SOFTWARE.
|
|||
*/
|
||||
|
||||
|
||||
#pragma name sfxp1
|
||||
#pragma parameter SFX_CLR "ScaleFX Color Thresh" 0.35 0.0 1.00 0.01
|
||||
layout(push_constant) uniform Push
|
||||
{
|
||||
vec4 SourceSize;
|
||||
float SFX_CLR;
|
||||
float SFX_SAA;
|
||||
} params;
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform float SFX_CLR;
|
||||
#else
|
||||
#define SFX_CLR 0.35
|
||||
#endif
|
||||
|
||||
const float THR = 1.0 - SFX_CLR;
|
||||
#pragma parameter SFX_CLR "ScaleFX Threshold" 0.50 0.01 1.00 0.01
|
||||
#pragma parameter SFX_SAA "ScaleFX Filter AA" 1.00 0.00 1.00 1.00
|
||||
|
||||
|
||||
layout(set = 0, binding = 0, std140) uniform UBO
|
||||
{
|
||||
mat4 MVP;
|
||||
vec4 SourceSize;
|
||||
};
|
||||
} global;
|
||||
|
||||
|
||||
#pragma stage vertex
|
||||
|
@ -67,7 +66,7 @@ layout(location = 0) out vec2 vTexCoord;
|
|||
|
||||
void main()
|
||||
{
|
||||
gl_Position = MVP * Position;
|
||||
gl_Position = global.MVP * Position;
|
||||
vTexCoord = TexCoord;
|
||||
}
|
||||
|
||||
|
@ -78,34 +77,12 @@ layout(location = 0) out vec4 FragColor;
|
|||
layout(binding = 1) uniform sampler2D Source;
|
||||
|
||||
|
||||
#define LE(x, y) (1.0 - step(y, x))
|
||||
#define GE(x, y) (1.0 - step(x, y))
|
||||
#define LEQ(x, y) step(x, y)
|
||||
#define GEQ(x, y) step(y, x)
|
||||
#define NOT(x) (1.0 - (x))
|
||||
|
||||
|
||||
// corner strength
|
||||
vec4 str(vec4 crn, vec4 ort){
|
||||
//return (crn > THR) ? max(2.0*crn - (ort + ort.wxyz), 0.0) : 0.0;
|
||||
return GE(crn, vec4(THR)) * max(2.0*crn - (ort + ort.wxyz), vec4(0.0));
|
||||
}
|
||||
|
||||
// corner dominance at junctions
|
||||
vec4 dom(vec3 strx, vec3 stry, vec3 strz, vec3 strw){
|
||||
vec4 res;
|
||||
res.x = max(2.0*strx.y - (strx.x + strx.z), 0.0);
|
||||
res.y = max(2.0*stry.y - (stry.x + stry.z), 0.0);
|
||||
res.z = max(2.0*strz.y - (strz.x + strz.z), 0.0);
|
||||
res.w = max(2.0*strw.y - (strw.x + strw.z), 0.0);
|
||||
return res;
|
||||
}
|
||||
|
||||
// necessary but not sufficient junction condition for orthogonal edges
|
||||
float clear(vec2 crn, vec4 ort){
|
||||
//return all(crn.xyxy <= THR || crn.xyxy <= ort || crn.xyxy <= ort.wxyz);
|
||||
vec4 res = LEQ(crn.xyxy, vec4(THR)) + LEQ(crn.xyxy, ort) + LEQ(crn.xyxy, ort.wxyz);
|
||||
return min(res.x * res.y * res.z * res.w, 1.0);
|
||||
float str(float d, vec2 a, vec2 b){
|
||||
float diff = a.x - a.y;
|
||||
float wght1 = max(params.SFX_CLR - d, 0) / params.SFX_CLR;
|
||||
float wght2 = clamp((1-d) + (min(a.x, b.x) + a.x > min(a.y, b.y) + a.y ? diff : -diff), 0, 1);
|
||||
return (params.SFX_SAA == 1 || 2*d < a.x + a.y) ? (wght1 * wght2) * (a.x * a.y) : 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -114,86 +91,25 @@ void main()
|
|||
|
||||
/* grid metric pattern
|
||||
|
||||
M A B C P x y z x y
|
||||
N D E F Q o w w z
|
||||
O G H I R
|
||||
J K L
|
||||
A B x y z x y
|
||||
D E F o w w z
|
||||
G H I
|
||||
*/
|
||||
|
||||
|
||||
#define TEX(x, y) textureOffset(Source, vTexCoord, ivec2(x, y))
|
||||
|
||||
|
||||
// metric data
|
||||
vec4 A = TEX(-1,-1), B = TEX( 0,-1), C = TEX( 1,-1);
|
||||
vec4 A = TEX(-1,-1), B = TEX( 0,-1);
|
||||
vec4 D = TEX(-1, 0), E = TEX( 0, 0), F = TEX( 1, 0);
|
||||
vec4 G = TEX(-1, 1), H = TEX( 0, 1), I = TEX( 1, 1);
|
||||
vec4 J = TEX(-1, 2), K = TEX( 0, 2), L = TEX( 1, 2);
|
||||
vec4 M = TEX(-2,-1), N = TEX(-2, 0), O = TEX(-2, 1);
|
||||
vec4 P = TEX( 2,-1), Q = TEX( 2, 0), R = TEX( 2, 1);
|
||||
|
||||
|
||||
// corner strength
|
||||
vec4 As = str(vec4(M.z, B.x, D.zx), vec4(A.yw, D.y, M.w));
|
||||
vec4 Bs = str(vec4(A.z, C.x, E.zx), vec4(B.yw, E.y, A.w));
|
||||
vec4 Cs = str(vec4(B.z, P.x, F.zx), vec4(C.yw, F.y, B.w));
|
||||
vec4 Ds = str(vec4(N.z, E.x, G.zx), vec4(D.yw, G.y, N.w));
|
||||
vec4 Es = str(vec4(D.z, F.x, H.zx), vec4(E.yw, H.y, D.w));
|
||||
vec4 Fs = str(vec4(E.z, Q.x, I.zx), vec4(F.yw, I.y, E.w));
|
||||
vec4 Gs = str(vec4(O.z, H.x, J.zx), vec4(G.yw, J.y, O.w));
|
||||
vec4 Hs = str(vec4(G.z, I.x, K.zx), vec4(H.yw, K.y, G.w));
|
||||
vec4 Is = str(vec4(H.z, R.x, L.zx), vec4(I.yw, L.y, H.w));
|
||||
|
||||
// strength & dominance junctions
|
||||
vec4 jSx = vec4(As.z, Bs.w, Es.x, Ds.y), jDx = dom(As.yzw, Bs.zwx, Es.wxy, Ds.xyz);
|
||||
vec4 jSy = vec4(Bs.z, Cs.w, Fs.x, Es.y), jDy = dom(Bs.yzw, Cs.zwx, Fs.wxy, Es.xyz);
|
||||
vec4 jSz = vec4(Es.z, Fs.w, Is.x, Hs.y), jDz = dom(Es.yzw, Fs.zwx, Is.wxy, Hs.xyz);
|
||||
vec4 jSw = vec4(Ds.z, Es.w, Hs.x, Gs.y), jDw = dom(Ds.yzw, Es.zwx, Hs.wxy, Gs.xyz);
|
||||
|
||||
|
||||
// majority vote for ambiguous dominance junctions
|
||||
//bvec4 jx = jDx != 0.0 && jDx + jDx.zwxy > jDx.yzwx + jDx.wxyz;
|
||||
//bvec4 jy = jDy != 0.0 && jDy + jDy.zwxy > jDy.yzwx + jDy.wxyz;
|
||||
//bvec4 jz = jDz != 0.0 && jDz + jDz.zwxy > jDz.yzwx + jDz.wxyz;
|
||||
//bvec4 jw = jDw != 0.0 && jDw + jDw.zwxy > jDw.yzwx + jDw.wxyz;
|
||||
|
||||
vec4 jx = GE(jDx, vec4(0.0)) * GE(jDx + jDx.zwxy, jDx.yzwx + jDx.wxyz);
|
||||
vec4 jy = GE(jDy, vec4(0.0)) * GE(jDy + jDy.zwxy, jDy.yzwx + jDy.wxyz);
|
||||
vec4 jz = GE(jDz, vec4(0.0)) * GE(jDz + jDz.zwxy, jDz.yzwx + jDz.wxyz);
|
||||
vec4 jw = GE(jDw, vec4(0.0)) * GE(jDw + jDw.zwxy, jDw.yzwx + jDw.wxyz);
|
||||
|
||||
// inject strength without creating new contradictions
|
||||
//bvec4 res;
|
||||
//res.x = jx.z || !(jx.y || jx.w) && (jSx.z != 0.0 && (jx.x || jSx.x + jSx.z > jSx.y + jSx.w));
|
||||
//res.y = jy.w || !(jy.z || jy.x) && (jSy.w != 0.0 && (jy.y || jSy.y + jSy.w > jSy.x + jSy.z));
|
||||
//res.z = jz.x || !(jz.w || jz.y) && (jSz.x != 0.0 && (jz.z || jSz.x + jSz.z > jSz.y + jSz.w));
|
||||
//res.w = jw.y || !(jw.x || jw.z) && (jSw.y != 0.0 && (jw.w || jSw.y + jSw.w > jSw.x + jSw.z));
|
||||
|
||||
vec4 res;
|
||||
res.x = min(jx.z + (NOT(jx.y) * NOT(jx.w)) * (GE(jSx.z, 0.0) * (jx.x + GE(jSx.x + jSx.z, jSx.y + jSx.w))), 1.0);
|
||||
res.y = min(jy.w + (NOT(jy.z) * NOT(jy.x)) * (GE(jSy.w, 0.0) * (jy.y + GE(jSy.y + jSy.w, jSy.x + jSy.z))), 1.0);
|
||||
res.z = min(jz.x + (NOT(jz.w) * NOT(jz.y)) * (GE(jSz.x, 0.0) * (jz.z + GE(jSz.x + jSz.z, jSz.y + jSz.w))), 1.0);
|
||||
res.w = min(jw.y + (NOT(jw.x) * NOT(jw.z)) * (GE(jSw.y, 0.0) * (jw.w + GE(jSw.y + jSw.w, jSw.x + jSw.z))), 1.0);
|
||||
|
||||
|
||||
// single pixel & end of line detection
|
||||
//res = res && (bvec4(jx.z, jy.w, jz.x, jw.y) || !(res.wxyz && res.yzwx));
|
||||
res = min(res * (vec4(jx.z, jy.w, jz.x, jw.y) + NOT(res.wxyz * res.yzwx)), vec4(1.0));
|
||||
|
||||
|
||||
// output
|
||||
|
||||
vec4 clr;
|
||||
clr.x = clear(vec2(D.z, E.x), vec4(A.w, E.y, D.wy));
|
||||
clr.y = clear(vec2(E.z, F.x), vec4(B.w, F.y, E.wy));
|
||||
clr.z = clear(vec2(H.z, I.x), vec4(E.w, I.y, H.wy));
|
||||
clr.w = clear(vec2(G.z, H.x), vec4(D.w, H.y, G.wy));
|
||||
|
||||
vec4 low = max(vec4(E.yw, H.y, D.w), vec4(THR));
|
||||
|
||||
vec4 hori = vec4(low.x < max(D.w, A.w), low.x < max(E.w, B.w), low.z < max(E.w, H.w), low.z < max(D.w, G.w)) * clr; // horizontal edges
|
||||
vec4 vert = vec4(low.w < max(E.y, D.y), low.y < max(E.y, F.y), low.y < max(H.y, I.y), low.w < max(H.y, G.y)) * clr; // vertical edges
|
||||
vec4 or = vec4(A.w < D.y, B.w <= F.y, H.w < I.y, G.w <= G.y); // orientation
|
||||
|
||||
FragColor = (res + 2.0 * hori + 4.0 * vert + 8.0 * or) / 15.0;
|
||||
res.x = str(D.z, vec2(D.w, E.y), vec2(A.w, D.y));
|
||||
res.y = str(F.x, vec2(E.w, E.y), vec2(B.w, F.y));
|
||||
res.z = str(H.z, vec2(E.w, H.y), vec2(H.w, I.y));
|
||||
res.w = str(H.x, vec2(D.w, H.y), vec2(G.w, G.y));
|
||||
|
||||
FragColor = res;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
/*
|
||||
ScaleFX - Pass 2
|
||||
by Sp00kyFox, 2016-03-30
|
||||
by Sp00kyFox, 2017-03-01
|
||||
|
||||
Filter: Nearest
|
||||
Scale: 1x
|
||||
|
@ -14,8 +14,7 @@ ScaleFX interpolates edges up to level 6 and makes smooth transitions between
|
|||
different slopes. The filtered picture will only consist of colours present
|
||||
in the original.
|
||||
|
||||
Pass 2 determines which edge level is present and prepares tags for subpixel
|
||||
output in the final pass.
|
||||
Pass 2 resolves ambiguous configurations of corner candidates at pixel junctions.
|
||||
|
||||
|
||||
|
||||
|
@ -42,14 +41,15 @@ THE SOFTWARE.
|
|||
*/
|
||||
|
||||
|
||||
#pragma name sfxp2
|
||||
|
||||
layout(push_constant) uniform Push
|
||||
{
|
||||
vec4 SourceSize;
|
||||
} params;
|
||||
|
||||
layout(set = 0, binding = 0, std140) uniform UBO
|
||||
{
|
||||
mat4 MVP;
|
||||
vec4 SourceSize;
|
||||
};
|
||||
} global;
|
||||
|
||||
|
||||
#pragma stage vertex
|
||||
|
@ -59,7 +59,7 @@ layout(location = 0) out vec2 vTexCoord;
|
|||
|
||||
void main()
|
||||
{
|
||||
gl_Position = MVP * Position;
|
||||
gl_Position = global.MVP * Position;
|
||||
vTexCoord = TexCoord;
|
||||
}
|
||||
|
||||
|
@ -68,104 +68,92 @@ void main()
|
|||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(binding = 1) uniform sampler2D Source;
|
||||
layout(binding = 2) uniform sampler2D PassOutput0;
|
||||
|
||||
|
||||
// extract first bool4 from float4 - corners
|
||||
bvec4 loadCorn(vec4 x){
|
||||
return bvec4(floor(mod(x*15 + 0.5, 2.0)));
|
||||
#define LE(x, y) (1 - step(y, x))
|
||||
#define GE(x, y) (1 - step(x, y))
|
||||
#define LEQ(x, y) step(x, y)
|
||||
#define GEQ(x, y) step(y, x)
|
||||
#define NOT(x) (1 - (x))
|
||||
|
||||
// corner dominance at junctions
|
||||
vec4 dom(vec3 x, vec3 y, vec3 z, vec3 w){
|
||||
return 2 * vec4(x.y, y.y, z.y, w.y) - (vec4(x.x, y.x, z.x, w.x) + vec4(x.z, y.z, z.z, w.z));
|
||||
}
|
||||
|
||||
// extract second bool4 from float4 - horizontal edges
|
||||
bvec4 loadHori(vec4 x){
|
||||
return bvec4(floor(mod(x*7.5 + 0.25, 2.0)));
|
||||
// necessary but not sufficient junction condition for orthogonal edges
|
||||
float clear(vec2 crn, vec2 a, vec2 b){
|
||||
return (crn.x >= max(min(a.x, a.y), min(b.x, b.y))) && (crn.y >= max(min(a.x, b.y), min(b.x, a.y))) ? 1 : 0;
|
||||
}
|
||||
|
||||
// extract third bool4 from float4 - vertical edges
|
||||
bvec4 loadVert(vec4 x){
|
||||
return bvec4(floor(mod(x*3.75 + 0.125, 2.0)));
|
||||
}
|
||||
|
||||
// extract fourth bool4 from float4 - orientation
|
||||
bvec4 loadOr(vec4 x){
|
||||
return bvec4(floor(mod(x*1.875 + 0.0625, 2.0)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
/* grid corners mids
|
||||
/* grid metric pattern
|
||||
|
||||
B x y x
|
||||
D E F w y
|
||||
H w z z
|
||||
A B C x y z x y
|
||||
D E F o w w z
|
||||
G H I
|
||||
*/
|
||||
|
||||
#define TEX(x, y) textureOffset(Source, vTexCoord, ivec2(x, y))
|
||||
|
||||
// read data
|
||||
vec4 E = TEX( 0, 0);
|
||||
vec4 D = TEX(-1, 0), D0 = TEX(-2, 0), D1 = TEX(-3, 0);
|
||||
vec4 F = TEX( 1, 0), F0 = TEX( 2, 0), F1 = TEX( 3, 0);
|
||||
vec4 B = TEX( 0,-1), B0 = TEX( 0,-2), B1 = TEX( 0,-3);
|
||||
vec4 H = TEX( 0, 1), H0 = TEX( 0, 2), H1 = TEX( 0, 3);
|
||||
|
||||
// extract data
|
||||
bvec4 Ec = loadCorn(E), Eh = loadHori(E), Ev = loadVert(E), Eo = loadOr(E);
|
||||
bvec4 Dc = loadCorn(D), Dh = loadHori(D), Do = loadOr(D), D0c = loadCorn(D0), D0h = loadHori(D0), D1h = loadHori(D1);
|
||||
bvec4 Fc = loadCorn(F), Fh = loadHori(F), Fo = loadOr(F), F0c = loadCorn(F0), F0h = loadHori(F0), F1h = loadHori(F1);
|
||||
bvec4 Bc = loadCorn(B), Bv = loadVert(B), Bo = loadOr(B), B0c = loadCorn(B0), B0v = loadVert(B0), B1v = loadVert(B1);
|
||||
bvec4 Hc = loadCorn(H), Hv = loadVert(H), Ho = loadOr(H), H0c = loadCorn(H0), H0v = loadVert(H0), H1v = loadVert(H1);
|
||||
#define TEXm(x, y) textureOffset(PassOutput0, vTexCoord, ivec2(x, y))
|
||||
#define TEXs(x, y) textureOffset(Source, vTexCoord, ivec2(x, y))
|
||||
|
||||
|
||||
// lvl2 mid (left, right / up, down)
|
||||
bvec2 lvl2x = bvec2((Ec.x && Eh.y) && Dc.z, (Ec.y && Eh.x) && Fc.w);
|
||||
bvec2 lvl2y = bvec2((Ec.y && Ev.z) && Bc.w, (Ec.z && Ev.y) && Hc.x);
|
||||
bvec2 lvl2z = bvec2((Ec.w && Eh.z) && Dc.y, (Ec.z && Eh.w) && Fc.x);
|
||||
bvec2 lvl2w = bvec2((Ec.x && Ev.w) && Bc.z, (Ec.w && Ev.x) && Hc.y);
|
||||
// metric data
|
||||
vec4 A = TEXm(-1,-1), B = TEXm( 0,-1);
|
||||
vec4 D = TEXm(-1, 0), E = TEXm( 0, 0), F = TEXm( 1, 0);
|
||||
vec4 G = TEXm(-1, 1), H = TEXm( 0, 1), I = TEXm( 1, 1);
|
||||
|
||||
// lvl3 corners (hori, vert)
|
||||
bvec2 lvl3x = bvec2(lvl2x.y && (Dh.y && Dh.x) && Fh.z, lvl2w.y && (Bv.w && Bv.x) && Hv.z);
|
||||
bvec2 lvl3y = bvec2(lvl2x.x && (Fh.x && Fh.y) && Dh.w, lvl2y.y && (Bv.z && Bv.y) && Hv.w);
|
||||
bvec2 lvl3z = bvec2(lvl2z.x && (Fh.w && Fh.z) && Dh.x, lvl2y.x && (Hv.y && Hv.z) && Bv.x);
|
||||
bvec2 lvl3w = bvec2(lvl2z.y && (Dh.z && Dh.w) && Fh.y, lvl2w.x && (Hv.x && Hv.w) && Bv.y);
|
||||
// strength data
|
||||
vec4 As = TEXs(-1,-1), Bs = TEXs( 0,-1), Cs = TEXs( 1,-1);
|
||||
vec4 Ds = TEXs(-1, 0), Es = TEXs( 0, 0), Fs = TEXs( 1, 0);
|
||||
vec4 Gs = TEXs(-1, 1), Hs = TEXs( 0, 1), Is = TEXs( 1, 1);
|
||||
|
||||
// lvl4 corners (hori, vert)
|
||||
bvec2 lvl4x = bvec2((Dc.x && Dh.y && Eh.x && Eh.y && Fh.x && Fh.y) && (D0c.z && D0h.w), (Bc.x && Bv.w && Ev.x && Ev.w && Hv.x && Hv.w) && (B0c.z && B0v.y));
|
||||
bvec2 lvl4y = bvec2((Fc.y && Fh.x && Eh.y && Eh.x && Dh.y && Dh.x) && (F0c.w && F0h.z), (Bc.y && Bv.z && Ev.y && Ev.z && Hv.y && Hv.z) && (B0c.w && B0v.x));
|
||||
bvec2 lvl4z = bvec2((Fc.z && Fh.w && Eh.z && Eh.w && Dh.z && Dh.w) && (F0c.x && F0h.y), (Hc.z && Hv.y && Ev.z && Ev.y && Bv.z && Bv.y) && (H0c.x && H0v.w));
|
||||
bvec2 lvl4w = bvec2((Dc.w && Dh.z && Eh.w && Eh.z && Fh.w && Fh.z) && (D0c.y && D0h.x), (Hc.w && Hv.x && Ev.w && Ev.x && Bv.w && Bv.x) && (H0c.y && H0v.z));
|
||||
|
||||
// lvl5 mid (left, right / up, down)
|
||||
bvec2 lvl5x = bvec2(lvl4x.x && (F0h.x && F0h.y) && (D1h.z && D1h.w), lvl4y.x && (D0h.y && D0h.x) && (F1h.w && F1h.z));
|
||||
bvec2 lvl5y = bvec2(lvl4y.y && (H0v.y && H0v.z) && (B1v.w && B1v.x), lvl4z.y && (B0v.z && B0v.y) && (H1v.x && H1v.w));
|
||||
bvec2 lvl5z = bvec2(lvl4w.x && (F0h.w && F0h.z) && (D1h.y && D1h.x), lvl4z.x && (D0h.z && D0h.w) && (F1h.x && F1h.y));
|
||||
bvec2 lvl5w = bvec2(lvl4x.y && (H0v.x && H0v.w) && (B1v.z && B1v.y), lvl4w.y && (B0v.w && B0v.x) && (H1v.y && H1v.z));
|
||||
|
||||
// lvl6 corners (hori, vert)
|
||||
bvec2 lvl6x = bvec2(lvl5x.y && (D1h.y && D1h.x), lvl5w.y && (B1v.w && B1v.x));
|
||||
bvec2 lvl6y = bvec2(lvl5x.x && (F1h.x && F1h.y), lvl5y.y && (B1v.z && B1v.y));
|
||||
bvec2 lvl6z = bvec2(lvl5z.x && (F1h.w && F1h.z), lvl5y.x && (H1v.y && H1v.z));
|
||||
bvec2 lvl6w = bvec2(lvl5z.y && (D1h.z && D1h.w), lvl5w.x && (H1v.x && H1v.w));
|
||||
|
||||
|
||||
// subpixels - 0 = E, 1 = D, 2 = D0, 3 = F, 4 = F0, 5 = B, 6 = B0, 7 = H, 8 = H0
|
||||
|
||||
vec4 crn;
|
||||
crn.x = (Ec.x && Eo.x || lvl3x.x && Eo.y || lvl4x.x && Do.x || lvl6x.x && Fo.y) ? 5 : (Ec.x || lvl3x.y && !Eo.w || lvl4x.y && !Bo.x || lvl6x.y && !Ho.w) ? 1 : lvl3x.x ? 3 : lvl3x.y ? 7 : lvl4x.x ? 2 : lvl4x.y ? 6 : lvl6x.x ? 4 : lvl6x.y ? 8 : 0;
|
||||
crn.y = (Ec.y && Eo.y || lvl3y.x && Eo.x || lvl4y.x && Fo.y || lvl6y.x && Do.x) ? 5 : (Ec.y || lvl3y.y && !Eo.z || lvl4y.y && !Bo.y || lvl6y.y && !Ho.z) ? 3 : lvl3y.x ? 1 : lvl3y.y ? 7 : lvl4y.x ? 4 : lvl4y.y ? 6 : lvl6y.x ? 2 : lvl6y.y ? 8 : 0;
|
||||
crn.z = (Ec.z && Eo.z || lvl3z.x && Eo.w || lvl4z.x && Fo.z || lvl6z.x && Do.w) ? 7 : (Ec.z || lvl3z.y && !Eo.y || lvl4z.y && !Ho.z || lvl6z.y && !Bo.y) ? 3 : lvl3z.x ? 1 : lvl3z.y ? 5 : lvl4z.x ? 4 : lvl4z.y ? 8 : lvl6z.x ? 2 : lvl6z.y ? 6 : 0;
|
||||
crn.w = (Ec.w && Eo.w || lvl3w.x && Eo.z || lvl4w.x && Do.w || lvl6w.x && Fo.z) ? 7 : (Ec.w || lvl3w.y && !Eo.x || lvl4w.y && !Ho.w || lvl6w.y && !Bo.x) ? 1 : lvl3w.x ? 3 : lvl3w.y ? 5 : lvl4w.x ? 2 : lvl4w.y ? 8 : lvl6w.x ? 4 : lvl6w.y ? 6 : 0;
|
||||
|
||||
vec4 mid;
|
||||
mid.x = (lvl2x.x && Eo.x || lvl2x.y && Eo.y || lvl5x.x && Do.x || lvl5x.y && Fo.y) ? 5 : lvl2x.x ? 1 : lvl2x.y ? 3 : lvl5x.x ? 2 : lvl5x.y ? 4 : (Ec.x && Dc.z && Ec.y && Fc.w) ? ( Eo.x ? Eo.y ? 5 : 3 : 1) : 0;
|
||||
mid.y = (lvl2y.x && !Eo.y || lvl2y.y && !Eo.z || lvl5y.x && !Bo.y || lvl5y.y && !Ho.z) ? 3 : lvl2y.x ? 5 : lvl2y.y ? 7 : lvl5y.x ? 6 : lvl5y.y ? 8 : (Ec.y && Bc.w && Ec.z && Hc.x) ? (!Eo.y ? !Eo.z ? 3 : 7 : 5) : 0;
|
||||
mid.z = (lvl2z.x && Eo.w || lvl2z.y && Eo.z || lvl5z.x && Do.w || lvl5z.y && Fo.z) ? 7 : lvl2z.x ? 1 : lvl2z.y ? 3 : lvl5z.x ? 2 : lvl5z.y ? 4 : (Ec.z && Fc.x && Ec.w && Dc.y) ? ( Eo.z ? Eo.w ? 7 : 1 : 3) : 0;
|
||||
mid.w = (lvl2w.x && !Eo.x || lvl2w.y && !Eo.w || lvl5w.x && !Bo.x || lvl5w.y && !Ho.w) ? 1 : lvl2w.x ? 5 : lvl2w.y ? 7 : lvl5w.x ? 6 : lvl5w.y ? 8 : (Ec.w && Hc.y && Ec.x && Bc.z) ? (!Eo.w ? !Eo.x ? 1 : 5 : 7) : 0;
|
||||
// strength & dominance junctions
|
||||
vec4 jSx = vec4(As.z, Bs.w, Es.x, Ds.y), jDx = dom(As.yzw, Bs.zwx, Es.wxy, Ds.xyz);
|
||||
vec4 jSy = vec4(Bs.z, Cs.w, Fs.x, Es.y), jDy = dom(Bs.yzw, Cs.zwx, Fs.wxy, Es.xyz);
|
||||
vec4 jSz = vec4(Es.z, Fs.w, Is.x, Hs.y), jDz = dom(Es.yzw, Fs.zwx, Is.wxy, Hs.xyz);
|
||||
vec4 jSw = vec4(Ds.z, Es.w, Hs.x, Gs.y), jDw = dom(Ds.yzw, Es.zwx, Hs.wxy, Gs.xyz);
|
||||
|
||||
|
||||
// ouput
|
||||
FragColor = (crn + 9 * mid) / 80;
|
||||
// majority vote for ambiguous dominance junctions
|
||||
vec4 zero4 = vec4(0);
|
||||
vec4 jx = min(GE(jDx, zero4) * (LEQ(jDx.yzwx, zero4) * LEQ(jDx.wxyz, zero4) + GE(jDx + jDx.zwxy, jDx.yzwx + jDx.wxyz)), 1);
|
||||
vec4 jy = min(GE(jDy, zero4) * (LEQ(jDy.yzwx, zero4) * LEQ(jDy.wxyz, zero4) + GE(jDy + jDy.zwxy, jDy.yzwx + jDy.wxyz)), 1);
|
||||
vec4 jz = min(GE(jDz, zero4) * (LEQ(jDz.yzwx, zero4) * LEQ(jDz.wxyz, zero4) + GE(jDz + jDz.zwxy, jDz.yzwx + jDz.wxyz)), 1);
|
||||
vec4 jw = min(GE(jDw, zero4) * (LEQ(jDw.yzwx, zero4) * LEQ(jDw.wxyz, zero4) + GE(jDw + jDw.zwxy, jDw.yzwx + jDw.wxyz)), 1);
|
||||
|
||||
|
||||
// inject strength without creating new contradictions
|
||||
vec4 res;
|
||||
res.x = min(jx.z + NOT(jx.y) * NOT(jx.w) * GE(jSx.z, 0) * (jx.x + GE(jSx.x + jSx.z, jSx.y + jSx.w)), 1);
|
||||
res.y = min(jy.w + NOT(jy.z) * NOT(jy.x) * GE(jSy.w, 0) * (jy.y + GE(jSy.y + jSy.w, jSy.x + jSy.z)), 1);
|
||||
res.z = min(jz.x + NOT(jz.w) * NOT(jz.y) * GE(jSz.x, 0) * (jz.z + GE(jSz.x + jSz.z, jSz.y + jSz.w)), 1);
|
||||
res.w = min(jw.y + NOT(jw.x) * NOT(jw.z) * GE(jSw.y, 0) * (jw.w + GE(jSw.y + jSw.w, jSw.x + jSw.z)), 1);
|
||||
|
||||
|
||||
// single pixel & end of line detection
|
||||
res = min(res * (vec4(jx.z, jy.w, jz.x, jw.y) + NOT(res.wxyz * res.yzwx)), 1);
|
||||
|
||||
|
||||
// output
|
||||
|
||||
vec4 clr;
|
||||
clr.x = clear(vec2(D.z, E.x), vec2(D.w, E.y), vec2(A.w, D.y));
|
||||
clr.y = clear(vec2(F.x, E.z), vec2(E.w, E.y), vec2(B.w, F.y));
|
||||
clr.z = clear(vec2(H.z, I.x), vec2(E.w, H.y), vec2(H.w, I.y));
|
||||
clr.w = clear(vec2(H.x, G.z), vec2(D.w, H.y), vec2(G.w, G.y));
|
||||
|
||||
vec4 h = vec4(min(D.w, A.w), min(E.w, B.w), min(E.w, H.w), min(D.w, G.w));
|
||||
vec4 v = vec4(min(E.y, D.y), min(E.y, F.y), min(H.y, I.y), min(H.y, G.y));
|
||||
|
||||
vec4 or = GE(h + vec4(D.w, E.w, E.w, D.w), v + vec4(E.y, E.y, H.y, H.y)); // orientation
|
||||
vec4 hori = LE(h, v) * clr; // horizontal edges
|
||||
vec4 vert = GE(h, v) * clr; // vertical edges
|
||||
|
||||
FragColor = (res + 2 * hori + 4 * vert + 8 * or) / 15;
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
/*
|
||||
ScaleFX - Pass 3
|
||||
by Sp00kyFox, 2016-03-30
|
||||
by Sp00kyFox, 2017-03-01
|
||||
|
||||
Filter: Nearest
|
||||
Scale: 3x
|
||||
Scale: 1x
|
||||
|
||||
ScaleFX is an edge interpolation algorithm specialized in pixel art. It was
|
||||
originally intended as an improvement upon Scale3x but became a new filter in
|
||||
|
@ -14,7 +14,8 @@ ScaleFX interpolates edges up to level 6 and makes smooth transitions between
|
|||
different slopes. The filtered picture will only consist of colours present
|
||||
in the original.
|
||||
|
||||
Pass 3 outputs subpixels based on previously calculated tags.
|
||||
Pass 3 determines which edge level is present and prepares tags for subpixel
|
||||
output in the final pass.
|
||||
|
||||
|
||||
|
||||
|
@ -41,14 +42,20 @@ THE SOFTWARE.
|
|||
*/
|
||||
|
||||
|
||||
#pragma name sfxp3
|
||||
layout(push_constant) uniform Push
|
||||
{
|
||||
vec4 SourceSize;
|
||||
float SFX_SCN;
|
||||
} params;
|
||||
|
||||
|
||||
#pragma parameter SFX_SCN "ScaleFX Filter Corners" 1.0 0.0 1.0 1.0
|
||||
|
||||
|
||||
layout(set = 0, binding = 0, std140) uniform UBO
|
||||
{
|
||||
mat4 MVP;
|
||||
vec4 SourceSize;
|
||||
};
|
||||
} global;
|
||||
|
||||
|
||||
#pragma stage vertex
|
||||
|
@ -58,7 +65,7 @@ layout(location = 0) out vec2 vTexCoord;
|
|||
|
||||
void main()
|
||||
{
|
||||
gl_Position = MVP * Position;
|
||||
gl_Position = global.MVP * Position;
|
||||
vTexCoord = TexCoord;
|
||||
}
|
||||
|
||||
|
@ -67,18 +74,26 @@ void main()
|
|||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(binding = 1) uniform sampler2D Source;
|
||||
layout(binding = 2) uniform sampler2D Original;
|
||||
|
||||
|
||||
|
||||
// extract corners
|
||||
vec4 loadCrn(vec4 x){
|
||||
return floor(mod(x*80.0 + 0.5, 9.0));
|
||||
// extract first bool4 from float4 - corners
|
||||
bvec4 loadCorn(vec4 x){
|
||||
return bvec4(floor(mod(x*15 + 0.5, 2)));
|
||||
}
|
||||
|
||||
// extract mids
|
||||
vec4 loadMid(vec4 x){
|
||||
return floor(mod(x*8.888888 + 0.055555, 9.0));
|
||||
// extract second bool4 from float4 - horizontal edges
|
||||
bvec4 loadHori(vec4 x){
|
||||
return bvec4(floor(mod(x*7.5 + 0.25, 2)));
|
||||
}
|
||||
|
||||
// extract third bool4 from float4 - vertical edges
|
||||
bvec4 loadVert(vec4 x){
|
||||
return bvec4(floor(mod(x*3.75 + 0.125, 2)));
|
||||
}
|
||||
|
||||
// extract fourth bool4 from float4 - orientation
|
||||
bvec4 loadOr(vec4 x){
|
||||
return bvec4(floor(mod(x*1.875 + 0.0625, 2)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -86,29 +101,83 @@ vec4 loadMid(vec4 x){
|
|||
void main()
|
||||
{
|
||||
|
||||
/* grid corners mids
|
||||
/* grid corners mids
|
||||
|
||||
B x y x
|
||||
D E F w y
|
||||
H w z z
|
||||
*/
|
||||
|
||||
#define TEX(x, y) textureOffset(Source, vTexCoord, ivec2(x, y))
|
||||
|
||||
// read data
|
||||
vec4 E = texture(Source, vTexCoord);
|
||||
vec4 E = TEX( 0, 0);
|
||||
vec4 D = TEX(-1, 0), D0 = TEX(-2, 0), D1 = TEX(-3, 0);
|
||||
vec4 F = TEX( 1, 0), F0 = TEX( 2, 0), F1 = TEX( 3, 0);
|
||||
vec4 B = TEX( 0,-1), B0 = TEX( 0,-2), B1 = TEX( 0,-3);
|
||||
vec4 H = TEX( 0, 1), H0 = TEX( 0, 2), H1 = TEX( 0, 3);
|
||||
|
||||
// extract data
|
||||
vec4 crn = loadCrn(E);
|
||||
vec4 mid = loadMid(E);
|
||||
bvec4 Ec = loadCorn(E), Eh = loadHori(E), Ev = loadVert(E), Eo = loadOr(E);
|
||||
bvec4 Dc = loadCorn(D), Dh = loadHori(D), Do = loadOr(D), D0c = loadCorn(D0), D0h = loadHori(D0), D1h = loadHori(D1);
|
||||
bvec4 Fc = loadCorn(F), Fh = loadHori(F), Fo = loadOr(F), F0c = loadCorn(F0), F0h = loadHori(F0), F1h = loadHori(F1);
|
||||
bvec4 Bc = loadCorn(B), Bv = loadVert(B), Bo = loadOr(B), B0c = loadCorn(B0), B0v = loadVert(B0), B1v = loadVert(B1);
|
||||
bvec4 Hc = loadCorn(H), Hv = loadVert(H), Ho = loadOr(H), H0c = loadCorn(H0), H0v = loadVert(H0), H1v = loadVert(H1);
|
||||
|
||||
// determine subpixel
|
||||
vec2 fp = floor(3.0 * fract(vTexCoord*SourceSize.xy));
|
||||
float sp = fp.y == 0 ? (fp.x == 0 ? crn.x : fp.x == 1 ? mid.x : crn.y) : (fp.y == 1 ? (fp.x == 0 ? mid.w : fp.x == 1 ? 0 : mid.y) : (fp.x == 0 ? crn.w : fp.x == 1 ? mid.z : crn.z));
|
||||
|
||||
// lvl1 corners (hori, vert)
|
||||
bool lvl1x = Ec.x && (Dc.z || Bc.z || params.SFX_SCN == 1);
|
||||
bool lvl1y = Ec.y && (Fc.w || Bc.w || params.SFX_SCN == 1);
|
||||
bool lvl1z = Ec.z && (Fc.x || Hc.x || params.SFX_SCN == 1);
|
||||
bool lvl1w = Ec.w && (Dc.y || Hc.y || params.SFX_SCN == 1);
|
||||
|
||||
// lvl2 mid (left, right / up, down)
|
||||
bvec2 lvl2x = bvec2((Ec.x && Eh.y) && Dc.z, (Ec.y && Eh.x) && Fc.w);
|
||||
bvec2 lvl2y = bvec2((Ec.y && Ev.z) && Bc.w, (Ec.z && Ev.y) && Hc.x);
|
||||
bvec2 lvl2z = bvec2((Ec.w && Eh.z) && Dc.y, (Ec.z && Eh.w) && Fc.x);
|
||||
bvec2 lvl2w = bvec2((Ec.x && Ev.w) && Bc.z, (Ec.w && Ev.x) && Hc.y);
|
||||
|
||||
// lvl3 corners (hori, vert)
|
||||
bvec2 lvl3x = bvec2(lvl2x.y && (Dh.y && Dh.x) && Fh.z, lvl2w.y && (Bv.w && Bv.x) && Hv.z);
|
||||
bvec2 lvl3y = bvec2(lvl2x.x && (Fh.x && Fh.y) && Dh.w, lvl2y.y && (Bv.z && Bv.y) && Hv.w);
|
||||
bvec2 lvl3z = bvec2(lvl2z.x && (Fh.w && Fh.z) && Dh.x, lvl2y.x && (Hv.y && Hv.z) && Bv.x);
|
||||
bvec2 lvl3w = bvec2(lvl2z.y && (Dh.z && Dh.w) && Fh.y, lvl2w.x && (Hv.x && Hv.w) && Bv.y);
|
||||
|
||||
// lvl4 corners (hori, vert)
|
||||
bvec2 lvl4x = bvec2((Dc.x && Dh.y && Eh.x && Eh.y && Fh.x && Fh.y) && (D0c.z && D0h.w), (Bc.x && Bv.w && Ev.x && Ev.w && Hv.x && Hv.w) && (B0c.z && B0v.y));
|
||||
bvec2 lvl4y = bvec2((Fc.y && Fh.x && Eh.y && Eh.x && Dh.y && Dh.x) && (F0c.w && F0h.z), (Bc.y && Bv.z && Ev.y && Ev.z && Hv.y && Hv.z) && (B0c.w && B0v.x));
|
||||
bvec2 lvl4z = bvec2((Fc.z && Fh.w && Eh.z && Eh.w && Dh.z && Dh.w) && (F0c.x && F0h.y), (Hc.z && Hv.y && Ev.z && Ev.y && Bv.z && Bv.y) && (H0c.x && H0v.w));
|
||||
bvec2 lvl4w = bvec2((Dc.w && Dh.z && Eh.w && Eh.z && Fh.w && Fh.z) && (D0c.y && D0h.x), (Hc.w && Hv.x && Ev.w && Ev.x && Bv.w && Bv.x) && (H0c.y && H0v.z));
|
||||
|
||||
// lvl5 mid (left, right / up, down)
|
||||
bvec2 lvl5x = bvec2(lvl4x.x && (F0h.x && F0h.y) && (D1h.z && D1h.w), lvl4y.x && (D0h.y && D0h.x) && (F1h.w && F1h.z));
|
||||
bvec2 lvl5y = bvec2(lvl4y.y && (H0v.y && H0v.z) && (B1v.w && B1v.x), lvl4z.y && (B0v.z && B0v.y) && (H1v.x && H1v.w));
|
||||
bvec2 lvl5z = bvec2(lvl4w.x && (F0h.w && F0h.z) && (D1h.y && D1h.x), lvl4z.x && (D0h.z && D0h.w) && (F1h.x && F1h.y));
|
||||
bvec2 lvl5w = bvec2(lvl4x.y && (H0v.x && H0v.w) && (B1v.z && B1v.y), lvl4w.y && (B0v.w && B0v.x) && (H1v.y && H1v.z));
|
||||
|
||||
// lvl6 corners (hori, vert)
|
||||
bvec2 lvl6x = bvec2(lvl5x.y && (D1h.y && D1h.x), lvl5w.y && (B1v.w && B1v.x));
|
||||
bvec2 lvl6y = bvec2(lvl5x.x && (F1h.x && F1h.y), lvl5y.y && (B1v.z && B1v.y));
|
||||
bvec2 lvl6z = bvec2(lvl5z.x && (F1h.w && F1h.z), lvl5y.x && (H1v.y && H1v.z));
|
||||
bvec2 lvl6w = bvec2(lvl5z.y && (D1h.z && D1h.w), lvl5w.x && (H1v.x && H1v.w));
|
||||
|
||||
|
||||
// subpixels - 0 = E, 1 = D, 2 = D0, 3 = F, 4 = F0, 5 = B, 6 = B0, 7 = H, 8 = H0
|
||||
|
||||
vec4 crn;
|
||||
crn.x = (lvl1x && Eo.x || lvl3x.x && Eo.y || lvl4x.x && Do.x || lvl6x.x && Fo.y) ? 5 : (lvl1x || lvl3x.y && !Eo.w || lvl4x.y && !Bo.x || lvl6x.y && !Ho.w) ? 1 : lvl3x.x ? 3 : lvl3x.y ? 7 : lvl4x.x ? 2 : lvl4x.y ? 6 : lvl6x.x ? 4 : lvl6x.y ? 8 : 0;
|
||||
crn.y = (lvl1y && Eo.y || lvl3y.x && Eo.x || lvl4y.x && Fo.y || lvl6y.x && Do.x) ? 5 : (lvl1y || lvl3y.y && !Eo.z || lvl4y.y && !Bo.y || lvl6y.y && !Ho.z) ? 3 : lvl3y.x ? 1 : lvl3y.y ? 7 : lvl4y.x ? 4 : lvl4y.y ? 6 : lvl6y.x ? 2 : lvl6y.y ? 8 : 0;
|
||||
crn.z = (lvl1z && Eo.z || lvl3z.x && Eo.w || lvl4z.x && Fo.z || lvl6z.x && Do.w) ? 7 : (lvl1z || lvl3z.y && !Eo.y || lvl4z.y && !Ho.z || lvl6z.y && !Bo.y) ? 3 : lvl3z.x ? 1 : lvl3z.y ? 5 : lvl4z.x ? 4 : lvl4z.y ? 8 : lvl6z.x ? 2 : lvl6z.y ? 6 : 0;
|
||||
crn.w = (lvl1w && Eo.w || lvl3w.x && Eo.z || lvl4w.x && Do.w || lvl6w.x && Fo.z) ? 7 : (lvl1w || lvl3w.y && !Eo.x || lvl4w.y && !Ho.w || lvl6w.y && !Bo.x) ? 1 : lvl3w.x ? 3 : lvl3w.y ? 5 : lvl4w.x ? 2 : lvl4w.y ? 8 : lvl6w.x ? 4 : lvl6w.y ? 6 : 0;
|
||||
|
||||
vec4 mid;
|
||||
mid.x = (lvl2x.x && Eo.x || lvl2x.y && Eo.y || lvl5x.x && Do.x || lvl5x.y && Fo.y) ? 5 : lvl2x.x ? 1 : lvl2x.y ? 3 : lvl5x.x ? 2 : lvl5x.y ? 4 : (Ec.x && Dc.z && Ec.y && Fc.w) ? ( Eo.x ? Eo.y ? 5 : 3 : 1) : 0;
|
||||
mid.y = (lvl2y.x && !Eo.y || lvl2y.y && !Eo.z || lvl5y.x && !Bo.y || lvl5y.y && !Ho.z) ? 3 : lvl2y.x ? 5 : lvl2y.y ? 7 : lvl5y.x ? 6 : lvl5y.y ? 8 : (Ec.y && Bc.w && Ec.z && Hc.x) ? (!Eo.y ? !Eo.z ? 3 : 7 : 5) : 0;
|
||||
mid.z = (lvl2z.x && Eo.w || lvl2z.y && Eo.z || lvl5z.x && Do.w || lvl5z.y && Fo.z) ? 7 : lvl2z.x ? 1 : lvl2z.y ? 3 : lvl5z.x ? 2 : lvl5z.y ? 4 : (Ec.z && Fc.x && Ec.w && Dc.y) ? ( Eo.z ? Eo.w ? 7 : 1 : 3) : 0;
|
||||
mid.w = (lvl2w.x && !Eo.x || lvl2w.y && !Eo.w || lvl5w.x && !Bo.x || lvl5w.y && !Ho.w) ? 1 : lvl2w.x ? 5 : lvl2w.y ? 7 : lvl5w.x ? 6 : lvl5w.y ? 8 : (Ec.w && Hc.y && Ec.x && Bc.z) ? (!Eo.w ? !Eo.x ? 1 : 5 : 7) : 0;
|
||||
|
||||
// output coordinate - 0 = E, 1 = D, 2 = D0, 3 = F, 4 = F0, 5 = B, 6 = B0, 7 = H, 8 = H0
|
||||
vec2 res = sp == 0 ? vec2(0,0) : sp == 1 ? vec2(-1,0) : sp == 2 ? vec2(-2,0) : sp == 3 ? vec2(1,0) : sp == 4 ? vec2(2,0) : sp == 5 ? vec2(0,-1) : sp == 6 ? vec2(0,-2) : sp == 7 ? vec2(0,1) : vec2(0,2);
|
||||
|
||||
// ouput
|
||||
FragColor = texture(Original, vTexCoord + 1/SourceSize.xy * res);
|
||||
FragColor = (crn + 9 * mid) / 80;
|
||||
|
||||
}
|
||||
|
|
159
scalefx/shaders/scalefx-pass4-hybrid.slang
Normal file
159
scalefx/shaders/scalefx-pass4-hybrid.slang
Normal file
|
@ -0,0 +1,159 @@
|
|||
#version 450
|
||||
|
||||
/*
|
||||
ScaleFX - Pass 4
|
||||
by Sp00kyFox, 2017-03-01
|
||||
|
||||
Filter: Nearest
|
||||
Scale: 3x
|
||||
|
||||
ScaleFX is an edge interpolation algorithm specialized in pixel art. It was
|
||||
originally intended as an improvement upon Scale3x but became a new filter in
|
||||
its own right.
|
||||
ScaleFX interpolates edges up to level 6 and makes smooth transitions between
|
||||
different slopes. The filtered picture will only consist of colours present
|
||||
in the original.
|
||||
|
||||
Pass 4 outputs subpixels based on previously calculated tags.
|
||||
|
||||
|
||||
|
||||
Copyright (c) 2016 Sp00kyFox - ScaleFX@web.de
|
||||
|
||||
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
|
||||
{
|
||||
vec4 SourceSize;
|
||||
float SFX_RAA;
|
||||
} params;
|
||||
|
||||
|
||||
#pragma parameter SFX_RAA "ScaleFX rAA Sharpness" 2.0 0.0 10.0 0.05
|
||||
|
||||
|
||||
layout(set = 0, binding = 0, std140) 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(binding = 1) uniform sampler2D Source;
|
||||
layout(binding = 2) uniform sampler2D Original;
|
||||
|
||||
|
||||
// extract corners
|
||||
vec4 loadCrn(vec4 x){
|
||||
return floor(mod(x*80 + 0.5, 9));
|
||||
}
|
||||
|
||||
// extract mids
|
||||
vec4 loadMid(vec4 x){
|
||||
return floor(mod(x*8.888888 + 0.055555, 9));
|
||||
}
|
||||
|
||||
vec3 res2x(vec3 pre2, vec3 pre1, vec3 px, vec3 pos1, vec3 pos2)
|
||||
{
|
||||
vec3 t, m;
|
||||
mat4x3 pre = mat4x3(pre2, pre1, px, pos1);
|
||||
mat4x3 pos = mat4x3(pre1, px, pos1, pos2);
|
||||
mat4x3 df = pos - pre;
|
||||
|
||||
m = mix(px, 1-px, step(px, vec3(0.5)));
|
||||
m = params.SFX_RAA * min(m, min(abs(df[1]), abs(df[2])));
|
||||
t = (7 * (df[1] + df[2]) - 3 * (df[0] + df[3])) / 16;
|
||||
t = clamp(t, -m, m);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
/* grid corners mids
|
||||
|
||||
B x y x
|
||||
D E F w y
|
||||
H w z z
|
||||
*/
|
||||
|
||||
|
||||
// read data
|
||||
vec4 E = texture(Source, vTexCoord);
|
||||
|
||||
// determine subpixel
|
||||
vec2 fc = fract(vTexCoord * params.SourceSize.xy);
|
||||
vec2 fp = floor(3.0 * fc);
|
||||
|
||||
// check adjacent pixels to prevent artifacts
|
||||
vec4 hn = texture(Source, vTexCoord + vec2(fp.x - 1, 0) / params.SourceSize.xy);
|
||||
vec4 vn = texture(Source, vTexCoord + vec2(0, fp.y - 1) / params.SourceSize.xy);
|
||||
|
||||
// extract data
|
||||
vec4 crn = loadCrn(E), hc = loadCrn(hn), vc = loadCrn(vn);
|
||||
vec4 mid = loadMid(E), hm = loadMid(hn), vm = loadMid(vn);
|
||||
|
||||
vec3 res = fp.y == 0 ? (fp.x == 0 ? vec3(crn.x, hc.y, vc.w) : fp.x == 1 ? vec3(mid.x, 0, vm.z) : vec3(crn.y, hc.x, vc.z)) : (fp.y == 1 ? (fp.x == 0 ? vec3(mid.w, hm.y, 0) : fp.x == 1 ? vec3(0) : vec3(mid.y, hm.w, 0)) : (fp.x == 0 ? vec3(crn.w, hc.z, vc.x) : fp.x == 1 ? vec3(mid.z, 0, vm.x) : vec3(crn.z, hc.w, vc.y)));
|
||||
|
||||
|
||||
#define TEX(x, y) textureOffset(Original, vTexCoord, ivec2(x, y)).rgb
|
||||
|
||||
// reverseAA
|
||||
vec3 E0 = TEX( 0, 0);
|
||||
vec3 B0 = TEX( 0,-1), B1 = TEX( 0,-2), H0 = TEX( 0, 1), H1 = TEX( 0, 2);
|
||||
vec3 D0 = TEX(-1, 0), D1 = TEX(-2, 0), F0 = TEX( 1, 0), F1 = TEX( 2, 0);
|
||||
|
||||
// output coordinate - 0 = E0, 1 = D0, 2 = D1, 3 = F0, 4 = F1, 5 = B0, 6 = B1, 7 = H0, 8 = H1
|
||||
vec3 sfx = res.x == 1 ? D0 : res.x == 2 ? D1 : res.x == 3 ? F0 : res.x == 4 ? F1 : res.x == 5 ? B0 : res.x == 6 ? B1 : res.x == 7 ? H0 : H1;
|
||||
|
||||
// rAA weight
|
||||
vec2 w = 2 * fc - 1;
|
||||
w.x = res.y == 0 ? w.x : 0;
|
||||
w.y = res.z == 0 ? w.y : 0;
|
||||
|
||||
// rAA filter
|
||||
vec3 t1 = res2x(D1, D0, E0, F0, F1);
|
||||
vec3 t2 = res2x(B1, B0, E0, H0, H1);
|
||||
|
||||
vec3 a = min(min(min(min(B0,D0),E0),F0),H0);
|
||||
vec3 b = max(max(max(max(B0,D0),E0),F0),H0);
|
||||
vec3 raa = clamp(E0 + w.x*t1 + w.y*t2, a, b);
|
||||
|
||||
// hybrid output
|
||||
FragColor = vec4((res.x != 0) ? sfx : raa, 0);
|
||||
}
|
114
scalefx/shaders/scalefx-pass4.slang
Normal file
114
scalefx/shaders/scalefx-pass4.slang
Normal file
|
@ -0,0 +1,114 @@
|
|||
#version 450
|
||||
|
||||
/*
|
||||
ScaleFX - Pass 4
|
||||
by Sp00kyFox, 2017-03-01
|
||||
|
||||
Filter: Nearest
|
||||
Scale: 3x
|
||||
|
||||
ScaleFX is an edge interpolation algorithm specialized in pixel art. It was
|
||||
originally intended as an improvement upon Scale3x but became a new filter in
|
||||
its own right.
|
||||
ScaleFX interpolates edges up to level 6 and makes smooth transitions between
|
||||
different slopes. The filtered picture will only consist of colours present
|
||||
in the original.
|
||||
|
||||
Pass 4 outputs subpixels based on previously calculated tags.
|
||||
|
||||
|
||||
|
||||
Copyright (c) 2016 Sp00kyFox - ScaleFX@web.de
|
||||
|
||||
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
|
||||
{
|
||||
vec4 SourceSize;
|
||||
} params;
|
||||
|
||||
|
||||
layout(set = 0, binding = 0, std140) 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(binding = 1) uniform sampler2D Source;
|
||||
layout(binding = 2) uniform sampler2D Original;
|
||||
|
||||
|
||||
// extract corners
|
||||
vec4 loadCrn(vec4 x){
|
||||
return floor(mod(x*80 + 0.5, 9));
|
||||
}
|
||||
|
||||
// extract mids
|
||||
vec4 loadMid(vec4 x){
|
||||
return floor(mod(x*8.888888 + 0.055555, 9));
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
/* grid corners mids
|
||||
|
||||
B x y x
|
||||
D E F w y
|
||||
H w z z
|
||||
*/
|
||||
|
||||
|
||||
// read data
|
||||
vec4 E = texture(Source, vTexCoord);
|
||||
|
||||
// extract data
|
||||
vec4 crn = loadCrn(E);
|
||||
vec4 mid = loadMid(E);
|
||||
|
||||
// determine subpixel
|
||||
vec2 fp = floor(3.0 * fract(vTexCoord * params.SourceSize.xy));
|
||||
float sp = fp.y == 0 ? (fp.x == 0 ? crn.x : fp.x == 1 ? mid.x : crn.y) : (fp.y == 1 ? (fp.x == 0 ? mid.w : fp.x == 1 ? 0 : mid.y) : (fp.x == 0 ? crn.w : fp.x == 1 ? mid.z : crn.z));
|
||||
|
||||
// output coordinate - 0 = E, 1 = D, 2 = D0, 3 = F, 4 = F0, 5 = B, 6 = B0, 7 = H, 8 = H0
|
||||
vec2 res = sp == 0 ? vec2(0,0) : sp == 1 ? vec2(-1,0) : sp == 2 ? vec2(-2,0) : sp == 3 ? vec2(1,0) : sp == 4 ? vec2(2,0) : sp == 5 ? vec2(0,-1) : sp == 6 ? vec2(0,-2) : sp == 7 ? vec2(0,1) : vec2(0,2);
|
||||
|
||||
// ouput
|
||||
FragColor = texture(Original, vTexCoord + res / params.SourceSize.xy);
|
||||
}
|
Loading…
Reference in a new issue