// [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); }