104 lines
2.9 KiB
Forth
104 lines
2.9 KiB
Forth
|
// [src] https://github.com/Hammster/windows-terminal-shaders (CC0)
|
||
|
|
||
|
// Settings
|
||
|
#define GRAIN_INTENSITY 0.02
|
||
|
#define TINT_COLOR vec4(1, 0.7f, 0, 0)
|
||
|
#define ENABLE_SCANLINES 1
|
||
|
#define ENABLE_REFRESHLINE 1
|
||
|
#define ENABLE_NOISE 1
|
||
|
#define ENABLE_CURVE 1
|
||
|
#define ENABLE_TINT 0
|
||
|
#define ENABLE_GRAIN 0
|
||
|
#define DEBUG 0
|
||
|
|
||
|
// Grain Lookup Table
|
||
|
#define a0 0.151015505647689
|
||
|
#define a1 -0.5303572634357367
|
||
|
#define a2 1.365020122861334
|
||
|
#define b0 0.132089632343748
|
||
|
#define b1 -0.7607324991323768
|
||
|
|
||
|
const vec4 tint = TINT_COLOR;
|
||
|
const vec4 scanlineTint = vec4(0.6f, 0.6f, 0.6f, 0.0f);
|
||
|
|
||
|
float permute(float x) {
|
||
|
x *= (34 * x + 1);
|
||
|
return 289 * fract(x * 1 / 289.0f);
|
||
|
}
|
||
|
|
||
|
float rand(float state) {
|
||
|
return fract(permute(state) / 41.0f);
|
||
|
}
|
||
|
|
||
|
float fmod(float x, float y) {
|
||
|
return x - y * trunc(x/y);
|
||
|
}
|
||
|
|
||
|
vec4 CRT( vec2 uv ) {
|
||
|
vec2 xy = uv;
|
||
|
|
||
|
#if ENABLE_CURVE
|
||
|
// TODO: add control variable for transform intensity
|
||
|
xy -= 0.5f; // offcenter screen
|
||
|
float r = xy.x * xy.x + xy.y * xy.y; // get ratio
|
||
|
xy *= 4.2f + r; // apply ratio
|
||
|
xy *= 0.25f; // zoom
|
||
|
xy += 0.5f; // move back to center
|
||
|
|
||
|
// TODO: add monitor visuals and make colors static consts
|
||
|
// Outter Box
|
||
|
if(xy.x < -0.025f || xy.y < -0.025f) return vec4(0, 0, 0, 0);
|
||
|
if(xy.x > 1.025f || xy.y > 1.025f) return vec4(0, 0, 0, 0);
|
||
|
// Bazel
|
||
|
if(xy.x < -0.015f || xy.y < -0.015f) return vec4(0.03f, 0.03f, 0.03f, 0.0f);
|
||
|
if(xy.x > 1.015f || xy.y > 1.015f) return vec4(0.03f, 0.03f, 0.03f, 0.0f);
|
||
|
// Screen Border
|
||
|
if(xy.x < 0.001f || xy.y < 0.001f) return vec4(0.0f, 0.0f, 0.0f, 0.0f);
|
||
|
if(xy.x > 0.999f || xy.y > 0.999f) return vec4(0.0f, 0.0f, 0.0f, 0.0f);
|
||
|
#endif
|
||
|
|
||
|
vec4 color = texture(iChannel0, xy);
|
||
|
|
||
|
#if DEBUG
|
||
|
if(xy.x < 0.5f) return color;
|
||
|
#endif
|
||
|
|
||
|
#if ENABLE_REFRESHLINE
|
||
|
float timeOver = fmod(iTime / 5, 1);
|
||
|
float refreshLineColorTint = timeOver - xy.y;
|
||
|
if(xy.y > timeOver && xy.y - 0.03f < timeOver ) color.rgb += (refreshLineColorTint * 2.0f);
|
||
|
#endif
|
||
|
|
||
|
#if ENABLE_SCANLINES
|
||
|
// scanlines are always every 1px
|
||
|
if(fmod(floor(uv.y * iResolution.y), 2) != 0) color *= scanlineTint;
|
||
|
#endif
|
||
|
|
||
|
#if ENABLE_TINT
|
||
|
float grayscale = (color.r + color.g + color.b) / 3.f;
|
||
|
color = vec4(grayscale, grayscale, grayscale, 0);
|
||
|
color *= tint;
|
||
|
#endif
|
||
|
|
||
|
#if ENABLE_GRAIN
|
||
|
vec3 m = vec3(tex, fmod(iTime, 5) / 5) + 1.;
|
||
|
float state = permute(permute(m.x) + m.y) + m.z;
|
||
|
|
||
|
float p = 0.95 * rand(state) + 0.025;
|
||
|
float q = p - 0.5;
|
||
|
float r2 = q * q;
|
||
|
|
||
|
float grain = q * (a2 + (a1 * r2 + a0) / (r2 * r2 + b1 * r2 + b0));
|
||
|
color.rgb += GRAIN_INTENSITY * grain;
|
||
|
#endif
|
||
|
|
||
|
return color;
|
||
|
}
|
||
|
|
||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||
|
vec2 uv = fragCoord.xy / iResolution.xy;
|
||
|
vec4 src = texture(iChannel0, uv);
|
||
|
|
||
|
fragColor = vec4(CRT(uv).rgb, src.a);
|
||
|
}
|