summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shaders/crt.f.glsl89
-rw-r--r--shaders/crt.v.glsl13
2 files changed, 102 insertions, 0 deletions
diff --git a/shaders/crt.f.glsl b/shaders/crt.f.glsl
new file mode 100644
index 0000000..d5fcde6
--- /dev/null
+++ b/shaders/crt.f.glsl
@@ -0,0 +1,89 @@
+#version 110
+
+/* Subtle CRT shader usable in fullscreen - Anaƫl Seghezzi [anael(at)maratis3d.com]
+ This shader is free software distributed under the terms of the GNU General Public
+ License version 3 or higher. This gives you the right to redistribute and/or
+ modify the program as long as you follow the terms of the license. See the file
+ COPYING for full license details.
+*/
+
+#define M_PI 3.14159265358979323846
+
+uniform sampler2D textures[2];
+uniform float width, height;
+varying vec2 texcoord;
+varying vec2 screencoord;
+
+
+float nrand(vec2 n) {
+ return fract(sin(dot(n.xy, vec2(12.9898, 78.233))) * 43758.5453);
+}
+
+float scanline(vec2 texco)
+{
+ return (1.0 - abs(cos(texco.y * 512.0 * M_PI)));
+}
+
+vec2 sharp_coord(vec2 texco, vec2 dim, vec2 sharpness)
+{
+ vec2 texcoif = texco * dim;
+ vec2 texcoi = floor(texcoif);
+ vec2 mu = (texcoif - 0.5) - texcoi;
+ vec2 mub = pow(abs(mu) * 2.0, sharpness) * sign(mu) * 0.5;
+ return (texcoi + mub + 0.5) / dim;
+}
+
+void main()
+{
+ float v = 1.0 / 512.0;
+ float yforce = 0.175;
+ float vign = length(screencoord);
+
+ // monitor deformation
+ vec2 monitorcoord = (screencoord + screencoord * vign * 0.025);
+
+ if (monitorcoord.x < -1.0 || monitorcoord.y < -1.0 || monitorcoord.x > 1.0 || monitorcoord.y > 1.0) {
+ gl_FragColor = vec4(0.0);
+ return;
+ }
+
+ vec2 texco = monitorcoord * vec2(width/1024.0, height/-1024.0) + vec2(width/1024.0, height/1024.0);
+
+ // mask
+ float maskx = 1.0 - pow(monitorcoord.x, 200.0);
+ float masky = 1.0 - pow(-monitorcoord.y, 200.0);
+ float mask = clamp(maskx * masky, 0.0, 1.0);
+
+ // sharp texcoord
+ vec2 texco_sharp0 = sharp_coord(texco, vec2(512.0, 512.0), vec2(4.0, 8.0));
+ vec2 texco_sharp1 = sharp_coord(texco - vec2(0.0, 1.0 / 1024.0), vec2(512.0, 512.0), vec2(4.0, 8.0));
+
+ vec4 src0 = texture2D(textures[0], texco_sharp0);
+ vec4 src1 = texture2D(textures[1], texco_sharp1);
+
+ // interlace mix
+ float interlace = cos((texco.y * 1024.0) * M_PI);
+ vec4 src_mix = mix(src0, src1, interlace * 0.5 + 0.5);
+
+ // blur
+ vec4 src_blur = mix(texture2D(textures[0], texco), texture2D(textures[1], texco), 0.5);
+
+#ifdef NO_SCANLINE
+
+ gl_FragColor = (src_mix * 0.95 + (src_blur * (1.6 - vign * 0.4) * 0.1)) * mask;
+
+#else
+ // multisample scanline with grain
+ // TODO: offset grain with time (needs a "frame" uniform)
+ float cosy;
+ cosy = scanline(texco + vec2(0.125, v * (nrand(texcoord + vec2(0.0, 1.0)) * 0.25) + 0.3333));
+ cosy += scanline(texco + vec2(0.25, v * (nrand(texcoord + vec2(0.0, 2.0)) * 0.25) + 0.25));
+ cosy += scanline(texco + vec2(0.50, v * (nrand(texcoord + vec2(0.0, 3.0)) * 0.25) + 0.6666));
+ cosy += scanline(texco + vec2(0.75, v * (nrand(texcoord + vec2(0.0, 4.0)) * 0.25) + 0.75));
+ cosy *= 0.25;
+
+ // final scanline + burn
+ gl_FragColor = ((src_mix * ((1.0 - yforce) + cosy * yforce)) + (src_blur * (1.6 - vign * 0.4) * 0.1)) * mask;
+
+#endif
+} \ No newline at end of file
diff --git a/shaders/crt.v.glsl b/shaders/crt.v.glsl
new file mode 100644
index 0000000..162d029
--- /dev/null
+++ b/shaders/crt.v.glsl
@@ -0,0 +1,13 @@
+#version 110
+
+attribute vec2 pos;
+varying vec2 texcoord;
+varying vec2 screencoord;
+uniform float width, height;
+
+void main()
+{
+ gl_Position = vec4(pos, 0.0, 1.0);
+ texcoord = sign(pos) * vec2(width/1024.0, height/-1024.0) + vec2(width/1024.0, height/1024.0);
+ screencoord = sign(pos);
+} \ No newline at end of file