mirror of
https://github.com/italicsjenga/slang-shaders.git
synced 2024-11-24 16:41:31 +11:00
add torridgristle's ps1 dedithering shaders
This commit is contained in:
parent
5aac649754
commit
2a3de628c1
6
dithering/ps1-dedither-boxblur.slangp
Normal file
6
dithering/ps1-dedither-boxblur.slangp
Normal file
|
@ -0,0 +1,6 @@
|
|||
shaders = 1
|
||||
|
||||
shader0 = shaders/ps1dither/PS1-Undither-BoxBlur.slang
|
||||
filter_linear0 = true
|
||||
scale_type0 = source
|
||||
scale0 = 1.0
|
11
dithering/ps1-dedither-comparison.slangp
Normal file
11
dithering/ps1-dedither-comparison.slangp
Normal 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
|
6
dithering/ps1-dither.slangp
Normal file
6
dithering/ps1-dither.slangp
Normal file
|
@ -0,0 +1,6 @@
|
|||
shaders = 1
|
||||
|
||||
shader0 = shaders/ps1dither/PS1-Undither-AntiBayer.slang
|
||||
filter_linear0 = true
|
||||
scale_type0 = source
|
||||
scale0 = 1.0
|
62
dithering/shaders/ps1dither/PS1-Undither-AntiBayer.slang
Normal file
62
dithering/shaders/ps1dither/PS1-Undither-AntiBayer.slang
Normal 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);
|
||||
}
|
66
dithering/shaders/ps1dither/PS1-Undither-BoxBlur.slang
Normal file
66
dithering/shaders/ps1dither/PS1-Undither-BoxBlur.slang
Normal 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);
|
||||
}
|
|
@ -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);
|
||||
}
|
77
dithering/shaders/ps1dither/PS1-Undither-Comparison.slang
Normal file
77
dithering/shaders/ps1dither/PS1-Undither-Comparison.slang
Normal 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);
|
||||
}
|
Loading…
Reference in a new issue