add torridgristle's ps1 dedithering shaders

This commit is contained in:
hunterk 2019-12-11 16:10:13 -06:00
parent 5aac649754
commit 2a3de628c1
7 changed files with 289 additions and 0 deletions

View file

@ -0,0 +1,6 @@
shaders = 1
shader0 = shaders/ps1dither/PS1-Undither-BoxBlur.slang
filter_linear0 = true
scale_type0 = source
scale0 = 1.0

View file

@ -0,0 +1,11 @@
shaders = 2
shader0 = shaders/ps1dither/PS1-Undither-AntiBayer.slang
filter_linear0 = true
scale_type0 = source
scale0 = 1.0
shader1 = shaders/ps1dither/PS1-Undither-Comparison-MkII.slang
filter_linear1 = true
scale_type1 = source
scale1 = 1.0

View file

@ -0,0 +1,6 @@
shaders = 1
shader0 = shaders/ps1dither/PS1-Undither-AntiBayer.slang
filter_linear0 = true
scale_type0 = source
scale0 = 1.0

View file

@ -0,0 +1,62 @@
#version 450
// PS1 Undither AntiBayer
// by torridgristle
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;
}
// PlayStation dithering pattern. The offset is selected based on the
// pixel position in VRAM, by blocks of 4x4 pixels. The value is added
// to the 8bit color components before they're truncated to 5 bits.
//"const int dither_pattern[16] ="
//" int[16](-4, 0, -3, 1,"
//" 2, -2, 3, -1,"
//" -3, 1, -4, 0,"
//" 3, -1, 2, -2);" "\n"
#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()
{
vec3 OriginPass = texture(Source, vTexCoord).xyz;
float PatternLUT[16] = float[](-4.0, 0.0, -3.0, 1.0,
2.0, -2.0, 3.0, -1.0,
-3.0, 1.0, -4.0, 0.0,
3.0, -1.0, 2.0, -2.0);
float PatternX = ceil(((mod(vTexCoord.x * params.SourceSize.x,4.00001)-0.5)/3.0)*3.0);
float PatternY = ceil(((mod(vTexCoord.y * params.SourceSize.y,4.00001)-0.5)/3.0)*3.0);
float Pattern = PatternLUT[int(PatternX+(PatternY*4))];
vec3 Result = OriginPass;
//Result = vec3(Pattern)/8.0 + 0.5;
Result = (Result * 255.0 - Pattern - round(Pattern*0.25)*2.0) / 255.0;
FragColor = vec4(Result,1.0);
}

View file

@ -0,0 +1,66 @@
#version 450
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()
{
vec3 OriginPass = texture(Source, vTexCoord).xyz;//No blending
//Blend 4 pixels together by sampling between them with linear interpolation
vec2 SquareBlend = (vTexCoord * params.SourceSize.xy - 0.5) * params.SourceSize.zw;
//Blend 2 horizontal pixels together the same way as before
vec2 HorizoBlend = (vTexCoord * params.SourceSize.xy - vec2(0.5,0.0)) * params.SourceSize.zw;
vec3 SquarePass = texture(Source, SquareBlend).xyz;
vec3 HorizoPass = texture(Source, HorizoBlend).xyz;
//Edge Detection for SquareBlend
vec3 SquareEdge = texture(Source, (SquareBlend * params.SourceSize.xy + vec2( 0.0, 1.0)) * params.SourceSize.zw).xyz +
texture(Source, (SquareBlend * params.SourceSize.xy + vec2( 1.0, 0.0)) * params.SourceSize.zw).xyz +
texture(Source, (SquareBlend * params.SourceSize.xy + vec2( 1.0, 1.0)) * params.SourceSize.zw).xyz;
SquareEdge = abs((SquareEdge / 3.0) - SquarePass);
//Try to adjust white / black range so that edges are black and non-edges are white
float SquareEdgeMask = 1.0-pow(1.0-pow(1.0-max(SquareEdge.x,max(SquareEdge.y,SquareEdge.z)),30.0),2.0);
//Edge Detection for HorizoBlend
vec3 HorizoEdge = texture(Source, (HorizoBlend * params.SourceSize.xy + vec2( 0.0, 1.0)) * params.SourceSize.zw).xyz +
texture(Source, (HorizoBlend * params.SourceSize.xy + vec2( 1.0, 0.0)) * params.SourceSize.zw).xyz +
texture(Source, (HorizoBlend * params.SourceSize.xy + vec2( 1.0, 1.0)) * params.SourceSize.zw).xyz;
HorizoEdge = abs((HorizoEdge / 3.0) - HorizoPass);
//Try to adjust white / black range so that edges are black and non-edges are white
float HorizoEdgeMask = 1.0-pow(1.0-pow(1.0-max(HorizoEdge.x,max(HorizoEdge.y,HorizoEdge.z)),10.0),2.0);
//If SquarePass has a detected edge, use HorizoPass
vec3 Result = mix(HorizoPass,SquarePass,SquareEdgeMask);
//If HorizoPass has a detected edge, use OriginPass
Result = mix(OriginPass,Result,HorizoEdgeMask);
//It's complete
FragColor = vec4(Result,1.0);
}

View file

@ -0,0 +1,61 @@
#version 450
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()
{
vec3 Sample1 = texture(Source, (vTexCoord * params.SourceSize.xy + vec2( 0.0, 0.0)) * params.SourceSize.zw).xyz;
vec3 Sample2 = texture(Source, (vTexCoord * params.SourceSize.xy + vec2( 1.0, 1.0)) * params.SourceSize.zw).xyz;
vec3 Sample3 = texture(Source, (vTexCoord * params.SourceSize.xy + vec2( 1.0, 0.0)) * params.SourceSize.zw).xyz;
vec3 Sample4 = texture(Source, (vTexCoord * params.SourceSize.xy + vec2( 0.0, 1.0)) * params.SourceSize.zw).xyz;
vec3 Average = (Sample1+Sample2+Sample3+Sample4)*0.25;
float Brightness = 1.0-pow(1.0-max(max(Average.x,Average.y),Average.z),2.0);
vec3 Sample2Diff = abs(Sample2-Sample1);
float Sample2DiffMax = max(max(Sample2Diff.x,Sample2Diff.y),Sample2Diff.z);
vec3 Sample3Diff = abs(Sample3-Sample1);
float Sample3DiffMax = max(max(Sample3Diff.x,Sample3Diff.y),Sample3Diff.z);
vec3 Sample4Diff = abs(Sample4-Sample1);
float Sample4DiffMax = max(max(Sample4Diff.x,Sample4Diff.y),Sample4Diff.z);
float DiffLimit = (Brightness * 4.0 + 2.0) / 32.0;
Sample2 = mix(Sample1,Sample2,vec3(Sample2DiffMax < DiffLimit));
Sample3 = mix(Sample1,Sample3,vec3(Sample3DiffMax < DiffLimit));
Sample4 = mix(Sample1,Sample4,vec3(Sample4DiffMax < DiffLimit));
vec3 Mixing = Sample1 + Sample2 + Sample3 + Sample4;
Mixing *= 0.25;
vec3 Result = vec3(Mixing);
FragColor = vec4(Result,1.0);
}

View file

@ -0,0 +1,77 @@
#version 450
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()
{
vec3 OriginPass = texture(Source, vTexCoord).xyz;
//Get blended textures by offsetting between 4 pixels.
vec3 SquarePass1 = texture(Source, (vTexCoord * params.SourceSize.xy + vec2( 0.5, 0.5)) * params.SourceSize.zw).xyz;
vec3 SquarePass2 = texture(Source, (vTexCoord * params.SourceSize.xy + vec2(-0.5,-0.5)) * params.SourceSize.zw).xyz;
vec3 SquarePass3 = texture(Source, (vTexCoord * params.SourceSize.xy + vec2(-0.5, 0.5)) * params.SourceSize.zw).xyz;
vec3 SquarePass4 = texture(Source, (vTexCoord * params.SourceSize.xy + vec2( 0.5,-0.5)) * params.SourceSize.zw).xyz;
//Which SquarePass is closest to the OriginPass?
vec3 SquarePass1Diff = abs(SquarePass1 - OriginPass);
vec3 SquarePass2Diff = abs(SquarePass2 - OriginPass);
vec3 SquarePass3Diff = abs(SquarePass3 - OriginPass);
vec3 SquarePass4Diff = abs(SquarePass4 - OriginPass);
float SquarePass1DiffAvg = (SquarePass1Diff.x + SquarePass1Diff.y + SquarePass1Diff.z) / 3.0;
float SquarePass2DiffAvg = (SquarePass2Diff.x + SquarePass2Diff.y + SquarePass2Diff.z) / 3.0;
float SquarePass3DiffAvg = (SquarePass3Diff.x + SquarePass3Diff.y + SquarePass3Diff.z) / 3.0;
float SquarePass4DiffAvg = (SquarePass4Diff.x + SquarePass4Diff.y + SquarePass4Diff.z) / 3.0;
float SquarePassDiffAvgMin = min(SquarePass1DiffAvg,min(SquarePass2DiffAvg,min(SquarePass3DiffAvg,SquarePass4DiffAvg)));
vec3 SquarePass =
float(SquarePassDiffAvgMin == SquarePass1DiffAvg) * float(SquarePass1DiffAvg != SquarePass2DiffAvg) * float(SquarePass1DiffAvg != SquarePass3DiffAvg) * float(SquarePass1DiffAvg != SquarePass4DiffAvg) * SquarePass1 +
float(SquarePassDiffAvgMin == SquarePass2DiffAvg) * float(SquarePass2DiffAvg != SquarePass3DiffAvg) * float(SquarePass2DiffAvg != SquarePass4DiffAvg) * SquarePass2 +
float(SquarePassDiffAvgMin == SquarePass3DiffAvg) * float(SquarePass3DiffAvg != SquarePass4DiffAvg) * SquarePass3 +
float(SquarePassDiffAvgMin == SquarePass4DiffAvg) * SquarePass4;
//How different is the blended texture from the original texture?
//The difference between the least different and most different SquarePasses returns edges.
vec3 SquareCompareMin = min(SquarePass1Diff,min(SquarePass2Diff,min(SquarePass3Diff,SquarePass4Diff)));
vec3 SquareCompareMax = max(SquarePass1Diff,max(SquarePass2Diff,max(SquarePass3Diff,SquarePass4Diff)));
vec3 SquareCompareBoth = abs(SquareCompareMin - SquareCompareMax);
float SquareCompare = max(SquareCompareBoth.x,max(SquareCompareBoth.y,SquareCompareBoth.z));
//Turn a range of the comparison result into a mask. 2.5 just happens to work well, it's not set in stone or anything.
float SquareMask = 1.0-pow(1.0-min(max(SquareCompare*2.5,0.0),1.0),2.0);
//Blend it all together
vec3 Result = mix(SquarePass,OriginPass,SquareMask);
//Result = vec3(SquareMask);
FragColor = vec4(Result,1.0);
}