add scalefx and dreamscape shaders

This commit is contained in:
hunterk 2017-01-30 08:51:12 -06:00
parent 5007dcc68f
commit 6d7617f9d8
15 changed files with 1383 additions and 0 deletions

56
blurs/blur-gauss-h.slang Normal file
View file

@ -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);
}

56
blurs/blur-gauss-v.slang Normal file
View file

@ -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);
}

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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);
}

49
scalefx/scalefx-9x.slangp Normal file
View file

@ -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

21
scalefx/scalefx.slangp Normal file
View file

@ -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

View 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));
}

View 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;
}

View 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;
}

View 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);
}

View 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 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);
}