slang-shaders/scanlines/shaders/integer-scaling-scanlines.slang

90 lines
2.3 KiB
Plaintext
Raw Normal View History

/*
Simple pixel perfect scanlines for use *only* with interger scaling mode.
Perfect for low res output and low performance machines.
Also great if you dont want any moire patterns pin sharp scanlines
Use in combination with HDR mode in latest RetroArch and very bright
HDR monitors to get 'glowing' scanlines much like the original CRT's but sharper
Recommended setting for 720p 1 pixel width scalines at 2x or 3x scalings
Recommended setting for 1080p 2 or 3 pixel width scalines at 4x or 5x scalings
Recommended setting for 4K 4 or 5 pixel width scalines at 8x or 9x scalings
*/
#version 450
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
float ScanlineWidth;
float ScreenWidth;
float ScreenHeight;
} params;
#pragma parameter ScanlineWidth "Scanline Width" 4.0 0.0 20.0 1.0
#pragma parameter ScreenWidth "Screen Width" 3840.0 0.0 7680.0 1.0
#pragma parameter ScreenHeight "Screen Height" 2160.0 0.0 4320.0 1.0
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;
layout(location = 1) out float Scale;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
vec2 ScreenSize = max(params.OutputSize.xy, vec2(params.ScreenWidth, params.ScreenHeight));
if((params.SourceSize.x > ScreenSize.x) || (params.SourceSize.y > ScreenSize.y))
{
Scale = 1.0;
}
else
{
float ScaleFactor = 2.0;
while(((params.SourceSize.x * ScaleFactor) <= ScreenSize.x) && ((params.SourceSize.y * ScaleFactor) <= ScreenSize.y))
{
ScaleFactor += 1.0;
}
Scale = ScaleFactor - 1.0;
}
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 1) in float Scale;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
float ModInteger(float a, float b)
{
float m = a - floor((a + 0.5) / b) * b;
return floor(m + 0.5);
}
void main()
{
vec2 InPixels = (vTexCoord * params.SourceSize.xy) * vec2(Scale);
if(ModInteger(floor(InPixels.y), Scale) < params.ScanlineWidth)
{
FragColor = vec4(texture(Source, vTexCoord).xyz, 1.0);
}
else
{
FragColor = vec4(0.0,0.0,0.0,1.0);
}
}