Files
Shrender-Man/GodotRetro/Screen Shaders/NTSCBasic.shader
2026-03-02 02:17:04 +00:00

79 lines
2.3 KiB
GLSL
Executable File

//SHADER ORIGINALY CREADED BY "keijiro" FROM GITHUB
//MODIFIED AND PORTED TO GODOT BY AHOPNESS (@ahopness)
//LICENSE : MIT
//COMATIBLE WITH : GLES2, GLES3
//GITHUB LINK : https://github.com/keijiro/KinoTube/
shader_type canvas_item;
const float PI = 3.14159265359;
uniform float _bleeding :hint_range(0, 1) = 0.5;
uniform float _fringing :hint_range(0, 1) = 0.5;
uniform float _scanline :hint_range(0, 1) = 0.5;
uniform bool linearColorSpace = true;
vec3 LinearToGammaSpace (vec3 linRGB){
linRGB = max(linRGB, vec3(0, 0, 0));
return max(1.055 * pow(linRGB, vec3(0.416666667)) - 0.055, 0);
}
vec3 GammaToLinearSpace (vec3 sRGB){
return sRGB * (sRGB * (sRGB * 0.305306011 + 0.682171111) + 0.012522878);
}
vec3 RGB2YIQ(vec3 rgb){
rgb = clamp(rgb, 0, 1);
if (!linearColorSpace){
rgb = LinearToGammaSpace(rgb);
}
return mat3(vec3(0.299, 0.587, 0.114),
vec3(0.596, -0.274, -0.322),
vec3(0.211, -0.523, 0.313)) * rgb;
}
vec3 YIQ2RGB(vec3 yiq){
vec3 rgb = mat3(vec3(1, 0.956, 0.621),
vec3(1, -0.272, -0.647),
vec3(1, -1.106, 1.703)) * yiq;
rgb = clamp(rgb, 0, 1);
if (!linearColorSpace){
rgb = GammaToLinearSpace(rgb);
}
return rgb;
}
vec3 SampleYIQ(vec2 uv, float du, sampler2D _MainTex){
uv.x += du;
return RGB2YIQ(texture(_MainTex, uv).rgb);
}
void fragment(){
float bleedWidth = 0.04 * _bleeding; // width of bleeding
float bleedStep = 2.5 / (1.0 / SCREEN_PIXEL_SIZE).x; // max interval of taps
float bleedTaps = ceil(bleedWidth / bleedStep);
float bleedDelta = bleedWidth / bleedTaps;
float fringeWidth = 0.0025 * _fringing; // width of fringing
vec2 uv = FRAGCOORD.xy / (1.0 / SCREEN_PIXEL_SIZE).xy;
vec3 yiq = SampleYIQ(uv, 0, SCREEN_TEXTURE);
// Bleeding
for (float i = 0.0; i < bleedTaps; i++)
{
yiq.y += SampleYIQ(uv, - bleedTaps * i, SCREEN_TEXTURE).y;
yiq.z += SampleYIQ(uv, + bleedTaps * i, SCREEN_TEXTURE).z;
}
yiq.yz /= bleedTaps + 1.0;
// Fringing
float y1 = SampleYIQ(uv, - fringeWidth, SCREEN_TEXTURE).x;
float y2 = SampleYIQ(uv, + fringeWidth, SCREEN_TEXTURE).x;
yiq.yz += y2 - y1;
// Scanline
float scan = sin(uv.y * 500.0 * PI);
scan = mix(1.0, (scan + 1.0) / 2.0, _scanline);
COLOR = vec4(YIQ2RGB(yiq * scan), 1);
}