mirror of
https://github.com/libretro/slang-shaders.git
synced 2024-11-23 00:10:03 +00:00
Add edgeNpixels shader (#630)
Co-authored-by: Andrei Timofeev <andrei.timofeev@mobirate.com>
This commit is contained in:
parent
b9e012f25c
commit
1b2ad364b7
5
pixel-art-scaling/edgeNpixels.slangp
Normal file
5
pixel-art-scaling/edgeNpixels.slangp
Normal file
@ -0,0 +1,5 @@
|
||||
shaders = 1
|
||||
|
||||
shader0 = shaders/edgeNpixels.slang
|
||||
filter_linear0 = true
|
||||
scale_type0 = viewport
|
@ -1,6 +1,7 @@
|
||||
#version 450
|
||||
|
||||
// Interpolate a single row of display pixels between each pair of adjacent source pixels.
|
||||
// Insert a single interpolated display (high-res)
|
||||
// pixel row between each pair of adjacent source (low-res) pixels.
|
||||
// by decavoid
|
||||
|
||||
|
||||
@ -20,22 +21,21 @@ layout(std140, set = 0, binding = 0) uniform UBO
|
||||
#pragma stage vertex
|
||||
layout(location = 0) in vec4 Position;
|
||||
layout(location = 1) in vec2 TexCoord;
|
||||
layout(location = 0) out vec2 vTexCoord;
|
||||
layout(location = 1) out vec2 inverseScale;
|
||||
layout(location = 0) out vec2 PixelCoords;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = global.MVP * Position;
|
||||
vTexCoord = TexCoord;
|
||||
inverseScale = vec2(params.OriginalSize.xy / params.OutputSize.xy);
|
||||
PixelCoords = TexCoord * params.SourceSize.xy; // NES x: [0; 256], y: [0; 240]
|
||||
}
|
||||
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 1) in vec2 inverseScale;
|
||||
layout(location = 0) in vec2 PixelCoords;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 2) uniform sampler2D Source;
|
||||
|
||||
vec2 inverseScaleHalf = vec2(params.OriginalSize.xy / params.OutputSize.xy) * 0.5;
|
||||
|
||||
vec2 isInside(vec2 v, vec2 left, vec2 right)
|
||||
{
|
||||
return step(left, v) - step(right, v);
|
||||
@ -46,11 +46,11 @@ vec2 isInside(vec2 v, vec2 left, vec2 right)
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 pixelCoords = vTexCoord * params.SourceSize.xy; // NES x: [0; 256], y: [0; 240]
|
||||
vec2 coordAtPixelCenter = (floor(pixelCoords) + vec2(0.5));
|
||||
vec2 coordBetweenPixels = round(pixelCoords);
|
||||
vec2 f = fract(pixelCoords) + vec2(1e-4);
|
||||
vec2 isFractionInside = isInside(f, 0.5 * inverseScale, 1.0 - 0.5 * inverseScale);
|
||||
vec2 iPixelCoords = floor(PixelCoords);
|
||||
vec2 coordAtPixelCenter = iPixelCoords + vec2(0.5);
|
||||
vec2 coordBetweenPixels = round(PixelCoords);
|
||||
vec2 f = fract(PixelCoords) + vec2(1e-3);
|
||||
vec2 isFractionInside = isInside(f, inverseScaleHalf, 1.0 - inverseScaleHalf);
|
||||
|
||||
/*
|
||||
Equivalent:
|
||||
@ -67,7 +67,7 @@ void main()
|
||||
*/
|
||||
|
||||
vec2 newCoord = isFractionInside * coordAtPixelCenter + (1 - isFractionInside) * coordBetweenPixels;
|
||||
vec2 newTexCoord = newCoord / params.SourceSize.xy;
|
||||
vec2 newTexCoord = newCoord * params.SourceSize.zw;
|
||||
FragColor = texture(Source, newTexCoord);
|
||||
|
||||
#ifdef DEBUG_DRAW_EDGES
|
||||
|
74
pixel-art-scaling/shaders/edgeNpixels.slang
Normal file
74
pixel-art-scaling/shaders/edgeNpixels.slang
Normal file
@ -0,0 +1,74 @@
|
||||
#version 450
|
||||
|
||||
// Insert a configurable count (1, 2, 3...) of interpolated display (high-res)
|
||||
// pixel rows between each pair of adjacent source (low-res) pixels.
|
||||
// by decavoid
|
||||
|
||||
|
||||
#pragma parameter PixelCount "Pixel Count" 2.0 1.0 8.0 1.0
|
||||
|
||||
layout(push_constant) uniform Push
|
||||
{
|
||||
vec4 SourceSize;
|
||||
vec4 OriginalSize;
|
||||
vec4 OutputSize;
|
||||
uint FrameCount;
|
||||
float PixelCount;
|
||||
} 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 PixelCoords;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = global.MVP * Position;
|
||||
PixelCoords = TexCoord * params.SourceSize.xy; // NES x: [0; 256], y: [0; 240]
|
||||
}
|
||||
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 PixelCoords;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 2) uniform sampler2D Source;
|
||||
|
||||
// uncomment to see a red grid of modified pixels
|
||||
//#define DEBUG_DRAW_EDGES
|
||||
|
||||
vec4 sizeScale = params.OutputSize / params.OriginalSize;
|
||||
vec2 interpolationRangeHalf = params.PixelCount * 0.5 * sizeScale.zw;
|
||||
float stepPerRow = 1.0 / (params.PixelCount + 1.0);
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 coordAtPixelCenter = (floor(PixelCoords) + vec2(0.5));
|
||||
vec2 coordBetweenPixels = round(PixelCoords);
|
||||
vec2 origOffset = PixelCoords - coordBetweenPixels + 1e-3; // [-0.5; 0.5]
|
||||
|
||||
vec2 needInterpolate = step(abs(origOffset), interpolationRangeHalf);
|
||||
|
||||
// if needInterpolate == 0, disable interpolation by choosing coordAtPixelCenter.
|
||||
//
|
||||
// if needInterpolate == 1, transform origOffset.x
|
||||
// from range [-interpolationRangeHalf.x; interpolationRangeHalf.x]
|
||||
// to range (-0.5; 0.5)
|
||||
vec2 segmentIndex = floor((origOffset + interpolationRangeHalf) * sizeScale.xy);
|
||||
vec2 transformedOffset = stepPerRow * (segmentIndex + 1) - 0.5;
|
||||
vec2 interpolatedCoord = coordBetweenPixels + transformedOffset;
|
||||
|
||||
vec2 newCoord = (1 - needInterpolate) * coordAtPixelCenter + needInterpolate * interpolatedCoord;
|
||||
vec2 newTexCoord = newCoord * params.SourceSize.zw;
|
||||
|
||||
FragColor = texture(Source, newTexCoord);
|
||||
|
||||
#ifdef DEBUG_DRAW_EDGES
|
||||
if (needInterpolate.x + needInterpolate.y > 0)
|
||||
FragColor.r = 1;
|
||||
#endif
|
||||
}
|
Loading…
Reference in New Issue
Block a user