mirror of
https://github.com/italicsjenga/slang-shaders.git
synced 2024-11-27 09:51:30 +11:00
fc7d957e50
To avoid duplicating the whole shader implementation, the needed define has been split into its own file, and the shader implementation is now in an include file.
109 lines
3.6 KiB
C++
109 lines
3.6 KiB
C++
/*
|
|
zfast_crt_standard - A simple, fast CRT shader.
|
|
|
|
Copyright (C) 2017 Greg Hogan (SoltanGris42)
|
|
|
|
This program is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU General Public License as published by the Free
|
|
Software Foundation; either version 2 of the License, or (at your option)
|
|
any later version.
|
|
|
|
|
|
Notes: This shader does scaling with a weighted linear filter for adjustable
|
|
sharpness on the x and y axes based on the algorithm by Inigo Quilez here:
|
|
http://http://www.iquilezles.org/www/articles/texture/texture.htm
|
|
but modified to be somewhat sharper. Then a scanline effect that varies
|
|
based on pixel brighness is applied along with a monochrome aperture mask.
|
|
This shader runs at 60fps on the Raspberry Pi 3 hardware at 2mpix/s
|
|
resolutions (1920x1080 or 1600x1200).
|
|
*/
|
|
|
|
layout(push_constant) uniform Push
|
|
{
|
|
vec4 SourceSize;
|
|
vec4 OriginalSize;
|
|
vec4 OutputSize;
|
|
uint FrameCount;
|
|
float BLURSCALEX, LOWLUMSCAN, HILUMSCAN, BRIGHTBOOST, MASK_DARK, MASK_FADE;
|
|
} params;
|
|
|
|
#pragma parameter BLURSCALEX "Blur Amount X-Axis" 0.30 0.0 1.0 0.05
|
|
#pragma parameter LOWLUMSCAN "Scanline Darkness - Low" 6.0 0.0 10.0 0.5
|
|
#pragma parameter HILUMSCAN "Scanline Darkness - High" 8.0 0.0 50.0 1.0
|
|
#pragma parameter BRIGHTBOOST "Dark Pixel Brightness Boost" 1.25 0.5 1.5 0.05
|
|
#pragma parameter MASK_DARK "Mask Effect Amount" 0.25 0.0 1.0 0.05
|
|
#pragma parameter MASK_FADE "Mask/Scanline Fade" 0.8 0.0 1.0 0.05
|
|
|
|
#define BLURSCALEX params.BLURSCALEX
|
|
#define LOWLUMSCAN params.LOWLUMSCAN
|
|
#define HILUMSCAN params.HILUMSCAN
|
|
#define BRIGHTBOOST params.BRIGHTBOOST
|
|
#define MASK_DARK params.MASK_DARK
|
|
#define MASK_FADE params.MASK_FADE
|
|
|
|
layout(std140, set = 0, binding = 0) uniform UBO
|
|
{
|
|
mat4 MVP;
|
|
} global;
|
|
|
|
//For testing compilation
|
|
//#define FRAGMENT
|
|
//#define VERTEX
|
|
|
|
//Some drivers don't return black with texture coordinates out of bounds
|
|
//SNES Classic is too slow to black these areas out when using fullscreen
|
|
//overlays. But you can uncomment the below to black them out if necessary
|
|
//#define BLACK_OUT_BORDER
|
|
|
|
#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 maskFade;
|
|
layout(location = 2) out vec2 invDims;
|
|
|
|
void main()
|
|
{
|
|
gl_Position = global.MVP * Position;
|
|
vTexCoord = TexCoord;
|
|
maskFade = 0.3333*MASK_FADE;
|
|
invDims = 1.0/params.SourceSize.xy;
|
|
}
|
|
|
|
#pragma stage fragment
|
|
layout(location = 0) in vec2 vTexCoord;
|
|
layout(location = 1) in float maskFade;
|
|
layout(location = 2) in vec2 invDims;
|
|
layout(location = 0) out vec4 FragColor;
|
|
layout(set = 0, binding = 2) uniform sampler2D Source;
|
|
|
|
void main()
|
|
{
|
|
//This is just like "Quilez Scaling" but sharper
|
|
vec2 p = vTexCoord * params.SourceSize.xy;
|
|
vec2 i = floor(p) + 0.50;
|
|
vec2 f = p - i;
|
|
p = (i + 4.0*f*f*f)*invDims;
|
|
p.x = mix( p.x , vTexCoord.x, BLURSCALEX);
|
|
float Y = f.y*f.y;
|
|
float YY = Y*Y;
|
|
|
|
#if defined(FINEMASK)
|
|
float whichmask = fract(floor(vTexCoord.x*params.OutputSize.x*-0.4999));
|
|
float mask = 1.0 + float(whichmask < 0.5) * -MASK_DARK;
|
|
#else
|
|
float whichmask = fract(floor(vTexCoord.x*params.OutputSize.x)*-0.3333);
|
|
float mask = 1.0 + float(whichmask <= 0.33333) * -MASK_DARK;
|
|
#endif
|
|
vec3 colour = texture(Source, p).rgb;
|
|
|
|
float scanLineWeight = (BRIGHTBOOST - LOWLUMSCAN*(Y - 2.05*YY));
|
|
float scanLineWeightB = 1.0 - HILUMSCAN*(YY-2.8*YY*Y);
|
|
|
|
#if defined(BLACK_OUT_BORDER)
|
|
colour.rgb*=float(tc.x > 0.0)*float(tc.y > 0.0); //why doesn't the driver do the right thing?
|
|
#endif
|
|
|
|
FragColor.rgb = colour.rgb*mix(scanLineWeight*mask, scanLineWeightB, dot(colour.rgb,vec3(maskFade)));
|
|
}
|