diff --git a/blurs/blur-gauss-h.slang b/blurs/blur-gauss-h.slang new file mode 100644 index 0000000..9d5693d --- /dev/null +++ b/blurs/blur-gauss-h.slang @@ -0,0 +1,56 @@ +#version 450 + +// Implementation based on the article "Efficient Gaussian blur with linear sampling" +// http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/ +/* A version for MasterEffect Reborn, a standalone version, and a custom shader version for SweetFX can be + found at http://reshade.me/forum/shader-presentation/27-gaussian-blur-bloom-unsharpmask */ + /*-----------------------------------------------------------. +/ Gaussian Blur settings / +'-----------------------------------------------------------*/ + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; +} params; + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; +} global; + +#define HW 1.00 + +#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; + +void main() +{ + vec2 texcoord = vTexCoord; + vec2 PIXEL_SIZE = params.SourceSize.zw; + + float sampleOffsets[5] = { 0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130 }; + float sampleWeights[5] = { 0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196 }; + + vec4 color = texture(Source, texcoord) * sampleWeights[0]; + for(int i = 1; i < 5; ++i) { + color += texture(Source, texcoord + vec2(sampleOffsets[i]*HW * PIXEL_SIZE.x, 0.0)) * sampleWeights[i]; + color += texture(Source, texcoord - vec2(sampleOffsets[i]*HW * PIXEL_SIZE.x, 0.0)) * sampleWeights[i]; + } + FragColor = vec4(color); +} \ No newline at end of file diff --git a/blurs/blur-gauss-v.slang b/blurs/blur-gauss-v.slang new file mode 100644 index 0000000..7eb304a --- /dev/null +++ b/blurs/blur-gauss-v.slang @@ -0,0 +1,56 @@ +#version 450 + +// Implementation based on the article "Efficient Gaussian blur with linear sampling" +// http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/ +/* A version for MasterEffect Reborn, a standalone version, and a custom shader version for SweetFX can be + found at http://reshade.me/forum/shader-presentation/27-gaussian-blur-bloom-unsharpmask */ + /*-----------------------------------------------------------. +/ Gaussian Blur settings / +'-----------------------------------------------------------*/ + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; +} params; + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; +} global; + +#define VW 1.00 + +#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; + +void main() +{ + vec2 texcoord = vTexCoord; + vec2 PIXEL_SIZE = params.SourceSize.zw; + + float sampleOffsets[5] = { 0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130 }; + float sampleWeights[5] = { 0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196 }; + + vec4 color = texture(Source, texcoord) * sampleWeights[0]; + for(int i = 1; i < 5; ++i) { + color += texture(Source, texcoord + vec2(0.0, sampleOffsets[i]*VW * PIXEL_SIZE.y)) * sampleWeights[i]; + color += texture(Source, texcoord - vec2(0.0, sampleOffsets[i]*VW * PIXEL_SIZE.y)) * sampleWeights[i]; + } + FragColor = vec4(color); +} \ No newline at end of file diff --git a/presets/scalefx9-aa-blur-hazy-ntsc-sh1nra358.slangp b/presets/scalefx9-aa-blur-hazy-ntsc-sh1nra358.slangp new file mode 100644 index 0000000..33d398d --- /dev/null +++ b/presets/scalefx9-aa-blur-hazy-ntsc-sh1nra358.slangp @@ -0,0 +1,93 @@ +shaders = 16 + +shader0 = ../scalefx/shaders/scalefx-pass0.slang +filter_linear0 = false +scale_type0 = source +scale0 = 1.0 +alias0 = sfxp0 + +shader1 = ../scalefx/shaders/scalefx-pass1.slang +filter_linear1 = false +scale_type1 = source +scale1 = 1.0 +alias1 = sfxp1 + +shader2 = ../scalefx/shaders/scalefx-pass2.slang +filter_linear2 = false +scale_type2 = source +scale2 = 1.0 +alias2 = sfxp2 + +shader3 = ../scalefx/shaders/scalefx-pass3.slang +filter_linear3 = false +scale_type3 = source +scale3 = 3.0 +alias3 = sfxp3 + +shader4 = ../scalefx/shaders/scalefx-pass0.slang +filter_linear4 = false +scale_type4 = source +scale4 = 1.0 +alias4 = sfxp4 + +shader5 = ../scalefx/shaders/scalefx-pass1.slang +filter_linear5 = false +scale_type5 = source +scale5 = 1.0 +alias5 = sfxp5 + +shader6 = ../scalefx/shaders/scalefx-pass2.slang +filter_linear6 = false +scale_type6 = source +scale6 = 1.0 +alias6 = sfxp6 + +shader7 = ../scalefx/shaders/scalefx-pass7.slang +filter_linear7 = false +scale_type7 = source +scale7 = 3.0 +alias7 = sfxp7 + +shader8 = ../misc/image-adjustment.slang +filter_linear8 = false +scale_type8 = source +scale8 = 1.0 + +shader9 = ../anti-aliasing/shaders/aa-shader-4.0.slang +filter_linear9 = true +scale_type9 = viewport +scale9 = 1.0 + +shader10 = ../reshade/shaders/scanlines.slang +filter_linear10 = false +scale_type10 = source +scale10 = 1.0 +alias10 = scanpass + +shader11 = ../reshade/shaders/bloom-pass-sh1nra358.slang +filter_linear11 = false +scale_type11 = source +scale11 = 1.0 + +shader12 = ../blurs/blur-gauss-h.slang +filter_linear12 = true +scale_type12 = source +scale12 = 1.0 + +shader13 = ../blurs/blur-gauss-v.slang +filter_linear13 = true +scale_type13 = source +scale13 = 1.0 + +shader14 = ../reshade/shaders/blur-haze-sh1nra358.slang +filter_linear14 = true +scale_type14 = source +scale14 = 1.0 + +shader15 = ../misc/ntsc-colors.slang +filter_linear15 = false +scale_type15 = source +scale15 = 1.0 + +parameters = "INTERNAL_RES" +INTERNAL_RES = 6.0 diff --git a/presets/scalefx9-aa-blur-hazy-vibrance-sh1nra358.slangp b/presets/scalefx9-aa-blur-hazy-vibrance-sh1nra358.slangp new file mode 100644 index 0000000..b0923df --- /dev/null +++ b/presets/scalefx9-aa-blur-hazy-vibrance-sh1nra358.slangp @@ -0,0 +1,93 @@ +shaders = 16 + +shader0 = ../scalefx/shaders/scalefx-pass0.slang +filter_linear0 = false +scale_type0 = source +scale0 = 1.0 +alias0 = sfxp0 + +shader1 = ../scalefx/shaders/scalefx-pass1.slang +filter_linear1 = false +scale_type1 = source +scale1 = 1.0 +alias1 = sfxp1 + +shader2 = ../scalefx/shaders/scalefx-pass2.slang +filter_linear2 = false +scale_type2 = source +scale2 = 1.0 +alias2 = sfxp2 + +shader3 = ../scalefx/shaders/scalefx-pass3.slang +filter_linear3 = false +scale_type3 = source +scale3 = 3.0 +alias3 = sfxp3 + +shader4 = ../scalefx/shaders/scalefx-pass0.slang +filter_linear4 = false +scale_type4 = source +scale4 = 1.0 +alias4 = sfxp4 + +shader5 = ../scalefx/shaders/scalefx-pass1.slang +filter_linear5 = false +scale_type5 = source +scale5 = 1.0 +alias5 = sfxp5 + +shader6 = ../scalefx/shaders/scalefx-pass2.slang +filter_linear6 = false +scale_type6 = source +scale6 = 1.0 +alias6 = sfxp6 + +shader7 = ../scalefx/shaders/scalefx-pass7.slang +filter_linear7 = false +scale_type7 = source +scale7 = 3.0 +alias7 = sfxp7 + +shader8 = ../misc/image-adjustment.slang +filter_linear8 = false +scale_type8 = source +scale8 = 1.0 + +shader9 = ../anti-aliasing/shaders/aa-shader-4.0.slang +filter_linear9 = true +scale_type9 = viewport +scale9 = 1.0 + +shader10 = ../reshade/shaders/scanlines.slang +filter_linear10 = false +scale_type10 = source +scale10 = 1.0 +alias10 = scanpass + +shader11 = ../reshade/shaders/bloom-pass-sh1nra358.slang +filter_linear11 = false +scale_type11 = source +scale11 = 1.0 + +shader12 = ../blurs/blur-gauss-h.slang +filter_linear12 = true +scale_type12 = source +scale12 = 1.0 + +shader13 = ../blurs/blur-gauss-v.slang +filter_linear13 = true +scale_type13 = source +scale13 = 1.0 + +shader14 = ../reshade/shaders/blur-haze-sh1nra358.slang +filter_linear14 = true +scale_type14 = source +scale14 = 1.0 + +shader15 = ../reshade/shaders/vibrance-pass-sh1nra358.slang +filter_linear15 = false +scale_type15 = source +scale15 = 1.0 + +parameters = "INTERNAL_RES" +INTERNAL_RES = 6.0 diff --git a/reshade/shaders/bloom-pass-sh1nra358.slang b/reshade/shaders/bloom-pass-sh1nra358.slang new file mode 100644 index 0000000..d52582e --- /dev/null +++ b/reshade/shaders/bloom-pass-sh1nra358.slang @@ -0,0 +1,45 @@ +#version 450 + +// Implementation based on the article "Efficient Gaussian blur with linear sampling" +// http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/ +/* A version for MasterEffect Reborn, a standalone version, and a custom shader version for SweetFX can be + found at http://reshade.me/forum/shader-presentation/27-gaussian-blur-bloom-unsharpmask */ + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; + float BloomIntensity; +} params; + +#pragma parameter BloomIntensity "BloomIntensity" 3.0 1.0 4.0 0.1 +#define BloomIntensity params.BloomIntensity + +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; + +void main() +{ + vec4 color = texture(Source, vTexCoord); + FragColor = vec4(color.rgb * pow (abs (max (color.r, max (color.g, color.b))), 2.0), 2.0f)*BloomIntensity; +} \ No newline at end of file diff --git a/reshade/shaders/blur-haze-sh1nra358.slang b/reshade/shaders/blur-haze-sh1nra358.slang new file mode 100644 index 0000000..44e26c1 --- /dev/null +++ b/reshade/shaders/blur-haze-sh1nra358.slang @@ -0,0 +1,161 @@ +#version 450 + +// Implementation based on the article "Efficient Gaussian blur with linear sampling" +// http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/ +/* A version for MasterEffect Reborn, a standalone version, and a custom shader version for SweetFX can be + found at http://reshade.me/forum/shader-presentation/27-gaussian-blur-bloom-unsharpmask */ + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; + float GaussStrength; + float BloomStrength; + float SW; + float BRIGHT; +} params; + + /*-----------------------------------------------------------. +/ Gaussian Blur settings / +'-----------------------------------------------------------*/ + +#pragma parameter GaussStrength "Gauss Strength" 0.30 0.0 1.0 0.01 +#define GaussStrength params.GaussStrength +#pragma parameter BloomStrength "Bloom Strength" 0.33 0.000 1.000 0.005 +#define BloomStrength params.BloomStrength +#pragma parameter SW "Haze Width" 2.0 1.0 4.0 0.25 +#define SW params.SW +#pragma parameter BRIGHT "Brightness adjust" 0.5 0.3 0.6 0.01 +#define BRIGHT params.BRIGHT + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; +} global; + +//GaussEffect +//0 = off, 1 = Blur, 2 = Unsharpmask (expensive), 3 = Bloom, 4 = Sketchy, 5 = effects image only. +#define GaussEffect 1 + +//GaussStrength +//[0.00 to 1.00] Amount of effect blended into the final image. +//#define GaussStrength 0.45 + +//addBloom +//Set to 1 to add bloom to Blur or Unsharpmask. 0 = off. Set GaussEffect to 0 for bloom only. +#define addBloom 1 +#define bloomPass 1 +#define USE_addBlur 0 + +//Bloom Strength +//[0.00 to 1.00] Amount of addBloom added to the final image. +//#define BloomStrength 0.33 + +//Bloom Intensity *also affects blur and unsharpmask* +//Makes bright spots brighter. Only works when BrightPass is set to 1. +//#define BloomIntensity 3.00 + +//GaussBloomWarmth +//0 = neutral, 1 = warm, 2 = hazy/foggy +#define GaussBloomWarmth 0 + +//SW is Slant. Higher numbers = wider bloom. +//#define SW 2.00 + +#define CoefLuma_G vec3(0.2126, 0.7152, 0.0722) // BT.709 & sRBG luma coefficient (Monitors and HD Television) +#define sharp_strength_luma_G (CoefLuma_G * GaussStrength + 0.2) +#define sharp_clampG 0.035 + +#define texCoordp vTexCoord + +#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; +layout(set = 0, binding = 3) uniform sampler2D scanpass; + +void main() +{ + vec2 texp = texCoordp; + vec2 texcoord = vTexCoord; + vec2 PIXEL_SIZE = params.SourceSize.zw; + + float sampleOffsets[5] = { 0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130 }; + float sampleWeights[5] = { 0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196 }; + + vec4 color = texture(Source, texcoord) * sampleWeights[0]; + for(int i = 1; i < 5; ++i) { + color += texture(Source, texcoord + vec2(sampleOffsets[i]*SW * PIXEL_SIZE.x, sampleOffsets[i] * PIXEL_SIZE.y)) * sampleWeights[i]; + color += texture(Source, texcoord - vec2(sampleOffsets[i]*SW * PIXEL_SIZE.x, sampleOffsets[i] * PIXEL_SIZE.y)) * sampleWeights[i]; + color += texture(Source, texcoord + vec2(-sampleOffsets[i]*SW * PIXEL_SIZE.x, sampleOffsets[i] * PIXEL_SIZE.y)) * sampleWeights[i]; + color += texture(Source, texcoord + vec2(sampleOffsets[i]*SW * PIXEL_SIZE.x, -sampleOffsets[i] * PIXEL_SIZE.y)) * sampleWeights[i]; + } + vec4 blur = BRIGHT*color; + + vec4 orig = texture(scanpass, texp); + + vec3 sharp; + #if (GaussEffect == 0) + orig = orig; + #elif (GaussEffect == 1) + // Blur... + orig = mix(orig, blur, GaussStrength); + #elif (GaussEffect == 2) + // Sharpening + sharp = orig.rgb - blur.rgb; + float sharp_luma = dot(sharp, sharp_strength_luma_G); + sharp_luma = clamp(sharp_luma, -sharp_clampG, sharp_clampG); + orig = orig + sharp_luma; + #elif (GaussEffect == 3) + // Bloom + #if (GaussBloomWarmth == 0) + orig = mix(orig, blur *4, GaussStrength); +// Neutral + #elif (GaussBloomWarmth == 1) + orig = mix(orig, max(orig *1.8 + (blur *5) - 1.0, 0.0), GaussStrength); // Warm and cheap + #else + orig = mix(orig, (1.0 - ((1.0 - orig) * (1.0 - blur *1.0))), GaussStrength); // Foggy bloom + #endif + #elif (GaussEffect == 4) + // Sketchy + sharp = orig.rgb - blur.rgb; + orig = vec4(1.0, 1.0, 1.0, 0.0) - min(orig, dot(sharp, sharp_strength_luma_G)) *3; + // orig = vec4(1.0, 1.0, 1.0, 0.0) - min(blur, orig); // Negative + #else + orig = blur; + #endif + + #if (addBloom == 1) + #if (GaussBloomWarmth == 0) + orig += mix(orig, blur *4, BloomStrength); + orig = orig * 0.5; + #elif (GaussBloomWarmth == 1) + orig += mix(orig, max(orig *1.8 + (blur *5) - 1.0, 0.0), BloomStrength); + orig = orig * 0.5; + #else + orig += mix(orig, (1.0 - ((1.0 - orig) * (1.0 - blur *1.0))), BloomStrength); + orig = orig * 0.5; + #endif + #else + orig = orig; + #endif + + #if (USE_addBlur == 1) + orig += mix(orig, blur2, BlurStrength); + //orig = blur2; + #endif + FragColor = orig; +} \ No newline at end of file diff --git a/reshade/shaders/scanlines.slang b/reshade/shaders/scanlines.slang new file mode 100644 index 0000000..df9a643 --- /dev/null +++ b/reshade/shaders/scanlines.slang @@ -0,0 +1,45 @@ +#version 450 + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; + float opacity; +} params; + +#pragma parameter opacity "Scanlines dark" 50.0 0.0 100.0 1.0 +#define opacity params.opacity + +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; + +void main() +{ + vec4 frame = texture(Source, vTexCoord); + vec2 fragpos = floor(vTexCoord.xy*params.OutputSize.xy); + vec4 background; + if (mod(fragpos.y,2.0) == 0.0) background = vec4(0.0, 0.0, 0.0, 1.0); else background = vec4(1.0, 1.0, 1.0, 0.0); + if (params.OutputSize.y > 1600) { if (mod(fragpos.y,4.0) < 2.0) background = vec4(0.0, 0.0, 0.0, 1.0); else background = vec4(1.0, 1.0, 1.0, 0.0);} + background.a *= opacity / 100.0; + FragColor = mix(frame, background, background.a); +} \ No newline at end of file diff --git a/reshade/shaders/vibrance-pass-sh1nra358.slang b/reshade/shaders/vibrance-pass-sh1nra358.slang new file mode 100644 index 0000000..3b58b0a --- /dev/null +++ b/reshade/shaders/vibrance-pass-sh1nra358.slang @@ -0,0 +1,62 @@ +#version 450 + +/** + * Vibrance + * by Christian Cann Schuldt Jensen ~ CeeJay.dk + * + * Vibrance intelligently boosts the saturation of pixels so pixels that had little color get a larger boost than pixels that had a lot. + * This avoids oversaturation of pixels that were already very saturated. + */ + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; +} params; + +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; + +void main() +{ + #ifndef Vibrance_RGB_balance //for backwards compatibility with setting presets for older version. + #define Vibrance_RGB_balance vec3(1.00, 1.00, 1.00) + #endif + #define Vibrance 0.5 + #define Vibrance_coeff vec3(Vibrance_RGB_balance.r * Vibrance, Vibrance_RGB_balance.g * Vibrance, Vibrance_RGB_balance.b * Vibrance) + + vec3 col = texture(Source, vTexCoord).rgb; + vec3 lumCoeff = vec3(0.212656, 0.715158, 0.072186); //Values to calculate luma with + + float luma = dot(lumCoeff, col); //calculate luma (grey) + + float max_color = max(col.r, max(col.g,col.b)); //Find the strongest color + float min_color = min(col.r, min(col.g,col.b)); //Find the weakest color + + float color_saturation = max_color - min_color; //The difference between the two is the saturation + + col.r = mix(luma, col.r, (1.0 + (Vibrance_coeff.r * (1.0 - (sign(Vibrance_coeff.r) * color_saturation))))); + col.g = mix(luma, col.g, (1.0 + (Vibrance_coeff.g * (1.0 - (sign(Vibrance_coeff.g) * color_saturation))))); + col.b = mix(luma, col.b, (1.0 + (Vibrance_coeff.b * (1.0 - (sign(Vibrance_coeff.b) * color_saturation))))); + FragColor = vec4(col, 1.0); +} \ No newline at end of file diff --git a/scalefx/scalefx-9x.slangp b/scalefx/scalefx-9x.slangp new file mode 100644 index 0000000..9bce582 --- /dev/null +++ b/scalefx/scalefx-9x.slangp @@ -0,0 +1,49 @@ +shaders = 8 + +shader0 = shaders/scalefx-pass0.slang +filter_linear0 = false +scale_type0 = source +scale0 = 1.0 +alias0 = sfxp0 + +shader1 = shaders/scalefx-pass1.slang +filter_linear1 = false +scale_type1 = source +scale1 = 1.0 +alias1 = sfxp1 + +shader2 = shaders/scalefx-pass2.slang +filter_linear2 = false +scale_type2 = source +scale2 = 1.0 +alias2 = sfxp2 + +shader3 = shaders/scalefx-pass3.slang +filter_linear3 = false +scale_type3 = source +scale3 = 3.0 +alias3 = sfxp3 + +shader4 = shaders/scalefx-pass0.slang +filter_linear4 = false +scale_type4 = source +scale4 = 1.0 +alias4 = sfxp4 + +shader5 = shaders/scalefx-pass1.slang +filter_linear5 = false +scale_type5 = source +scale5 = 1.0 +alias5 = sfxp5 + +shader6 = shaders/scalefx-pass2.slang +filter_linear6 = false +scale_type6 = source +scale6 = 1.0 +alias6 = sfxp6 + +shader7 = shaders/scalefx-pass7.slang +filter_linear7 = false +scale_type7 = source +scale7 = 3.0 +alias7 = sfxp7 diff --git a/scalefx/scalefx.slangp b/scalefx/scalefx.slangp new file mode 100644 index 0000000..9e2b6b6 --- /dev/null +++ b/scalefx/scalefx.slangp @@ -0,0 +1,21 @@ +shaders = 4 + +shader0 = shaders/scalefx-pass0.slang +filter_linear0 = false +scale_type0 = source +scale0 = 1.0 + +shader1 = shaders/scalefx-pass1.slang +filter_linear1 = false +scale_type1 = source +scale1 = 1.0 + +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 = 3.0 diff --git a/scalefx/shaders/scalefx-pass0.slang b/scalefx/shaders/scalefx-pass0.slang new file mode 100644 index 0000000..b4a07e4 --- /dev/null +++ b/scalefx/shaders/scalefx-pass0.slang @@ -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)); +} diff --git a/scalefx/shaders/scalefx-pass1.slang b/scalefx/shaders/scalefx-pass1.slang new file mode 100644 index 0000000..dc3c722 --- /dev/null +++ b/scalefx/shaders/scalefx-pass1.slang @@ -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; +} diff --git a/scalefx/shaders/scalefx-pass2.slang b/scalefx/shaders/scalefx-pass2.slang new file mode 100644 index 0000000..07d20f8 --- /dev/null +++ b/scalefx/shaders/scalefx-pass2.slang @@ -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; + +} diff --git a/scalefx/shaders/scalefx-pass3.slang b/scalefx/shaders/scalefx-pass3.slang new file mode 100644 index 0000000..b75c3f1 --- /dev/null +++ b/scalefx/shaders/scalefx-pass3.slang @@ -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); + +} diff --git a/scalefx/shaders/scalefx-pass7.slang b/scalefx/shaders/scalefx-pass7.slang new file mode 100644 index 0000000..807fb1d --- /dev/null +++ b/scalefx/shaders/scalefx-pass7.slang @@ -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 sfxp7 + + +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 sfxp3; + + + +// 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(sfxp3, vTexCoord + 1/SourceSize.xy * res); + +}