1#version 130 2 3/* 4 Hyllian's CRT Shader 5 6 Copyright (C) 2011-2015 Hyllian - sergiogdb@gmail.com 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 26*/ 27 28#pragma parameter PHOSPHOR "CRT - Phosphor ON/OFF" 0.0 0.0 1.0 1.0 29#pragma parameter VSCANLINES "CRT - Scanlines Direction" 0.0 0.0 1.0 1.0 30#pragma parameter InputGamma "CRT - Input gamma" 2.2 0.0 5.0 0.1 31#pragma parameter OutputGamma "CRT - Output Gamma" 2.2 0.0 5.0 0.1 32#pragma parameter SHARPNESS "CRT - Sharpness Hack" 2.0 1.0 5.0 1.0 33#pragma parameter COLOR_BOOST "CRT - Color Boost" 1.3 1.0 2.0 0.05 34#pragma parameter RED_BOOST "CRT - Red Boost" 1.0 1.0 2.0 0.01 35#pragma parameter GREEN_BOOST "CRT - Green Boost" 1.0 1.0 2.0 0.01 36#pragma parameter BLUE_BOOST "CRT - Blue Boost" 1.0 1.0 2.0 0.01 37#pragma parameter SCANLINES_STRENGTH "CRT - Scanline Strength" 1.0 0.0 1.0 0.02 38#pragma parameter BEAM_MIN_WIDTH "CRT - Min Beam Width" 0.60 0.0 1.0 0.02 39#pragma parameter BEAM_MAX_WIDTH "CRT - Max Beam Width" 0.80 0.0 1.0 0.02 40#pragma parameter CRT_ANTI_RINGING "CRT - Anti-Ringing" 0.8 0.0 1.0 0.1 41 42#define GAMMA_IN(color) pow(color, vec3(InputGamma, InputGamma, InputGamma)) 43#define GAMMA_OUT(color) pow(color, vec3(1.0 / OutputGamma, 1.0 / OutputGamma, 1.0 / OutputGamma)) 44 45// Horizontal cubic filter. 46 47// Some known filters use these values: 48 49// B = 0.0, C = 0.0 => Hermite cubic filter. 50// B = 1.0, C = 0.0 => Cubic B-Spline filter. 51// B = 0.0, C = 0.5 => Catmull-Rom Spline filter. This is the default used in this shader. 52// B = C = 1.0/3.0 => Mitchell-Netravali cubic filter. 53// B = 0.3782, C = 0.3109 => Robidoux filter. 54// B = 0.2620, C = 0.3690 => Robidoux Sharp filter. 55// B = 0.36, C = 0.28 => My best config for ringing elimination in pixel art (Hyllian). 56 57// For more info, see: http://www.imagemagick.org/Usage/img_diagrams/cubic_survey.gif 58 59#if defined(VERTEX) 60 61#if __VERSION__ >= 130 62#define COMPAT_VARYING out 63#define COMPAT_ATTRIBUTE in 64#define COMPAT_TEXTURE texture 65#else 66#define COMPAT_VARYING varying 67#define COMPAT_ATTRIBUTE attribute 68#define COMPAT_TEXTURE texture2D 69#endif 70 71#ifdef GL_ES 72#define COMPAT_PRECISION mediump 73#else 74#define COMPAT_PRECISION 75#endif 76 77COMPAT_ATTRIBUTE vec4 VertexCoord; 78COMPAT_ATTRIBUTE vec4 COLOR; 79COMPAT_ATTRIBUTE vec4 TexCoord; 80COMPAT_VARYING vec4 COL0; 81COMPAT_VARYING vec4 TEX0; 82 83vec4 _oPosition1; 84uniform mat4 MVPMatrix; 85uniform COMPAT_PRECISION int FrameDirection; 86uniform COMPAT_PRECISION int FrameCount; 87uniform COMPAT_PRECISION vec2 OutputSize; 88uniform COMPAT_PRECISION vec2 TextureSize; 89uniform COMPAT_PRECISION vec2 InputSize; 90 91// compatibility #defines 92#define vTexCoord TEX0.xy 93#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize 94#define OutSize vec4(OutputSize, 1.0 / OutputSize) 95 96#ifdef PARAMETER_UNIFORM 97uniform COMPAT_PRECISION float PHOSPHOR; 98uniform COMPAT_PRECISION float VSCANLINES; 99uniform COMPAT_PRECISION float InputGamma; 100uniform COMPAT_PRECISION float OutputGamma; 101uniform COMPAT_PRECISION float SHARPNESS; 102uniform COMPAT_PRECISION float COLOR_BOOST; 103uniform COMPAT_PRECISION float RED_BOOST; 104uniform COMPAT_PRECISION float GREEN_BOOST; 105uniform COMPAT_PRECISION float BLUE_BOOST; 106uniform COMPAT_PRECISION float SCANLINES_STRENGTH; 107uniform COMPAT_PRECISION float BEAM_MIN_WIDTH; 108uniform COMPAT_PRECISION float BEAM_MAX_WIDTH; 109uniform COMPAT_PRECISION float CRT_ANTI_RINGING; 110#else 111#define PHOSPHOR 0.0 112#define VSCANLINES 0.0 113#define InputGamma 2.2 114#define OutputGamma 2.2 115#define SHARPNESS 2.0 116#define COLOR_BOOST 1.3 117#define RED_BOOST 1.0 118#define GREEN_BOOST 1.0 119#define BLUE_BOOST 1.0 120#define SCANLINES_STRENGTH 1.0 121#define BEAM_MIN_WIDTH 0.60 122#define BEAM_MAX_WIDTH 0.80 123#define CRT_ANTI_RINGING 0.8 124#endif 125 126void main() 127{ 128 gl_Position = MVPMatrix * VertexCoord; 129 TEX0.xy = TexCoord.xy; 130} 131 132#elif defined(FRAGMENT) 133 134#ifdef GL_ES 135#ifdef GL_FRAGMENT_PRECISION_HIGH 136precision highp float; 137#else 138precision mediump float; 139#endif 140#define COMPAT_PRECISION mediump 141#else 142#define COMPAT_PRECISION 143#endif 144 145#if __VERSION__ >= 130 146#define COMPAT_VARYING in 147#define COMPAT_TEXTURE texture 148out COMPAT_PRECISION vec4 FragColor; 149#else 150#define COMPAT_VARYING varying 151#define FragColor gl_FragColor 152#define COMPAT_TEXTURE texture2D 153#endif 154 155uniform COMPAT_PRECISION int FrameDirection; 156uniform COMPAT_PRECISION int FrameCount; 157uniform COMPAT_PRECISION vec2 OutputSize; 158uniform COMPAT_PRECISION vec2 TextureSize; 159uniform COMPAT_PRECISION vec2 InputSize; 160uniform sampler2D Texture; 161COMPAT_VARYING vec4 TEX0; 162 163// compatibility #defines 164#define Source Texture 165#define vTexCoord TEX0.xy 166 167#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize 168#define OutSize vec4(OutputSize, 1.0 / OutputSize) 169 170#ifdef PARAMETER_UNIFORM 171uniform COMPAT_PRECISION float PHOSPHOR; 172uniform COMPAT_PRECISION float VSCANLINES; 173uniform COMPAT_PRECISION float InputGamma; 174uniform COMPAT_PRECISION float OutputGamma; 175uniform COMPAT_PRECISION float SHARPNESS; 176uniform COMPAT_PRECISION float COLOR_BOOST; 177uniform COMPAT_PRECISION float RED_BOOST; 178uniform COMPAT_PRECISION float GREEN_BOOST; 179uniform COMPAT_PRECISION float BLUE_BOOST; 180uniform COMPAT_PRECISION float SCANLINES_STRENGTH; 181uniform COMPAT_PRECISION float BEAM_MIN_WIDTH; 182uniform COMPAT_PRECISION float BEAM_MAX_WIDTH; 183uniform COMPAT_PRECISION float CRT_ANTI_RINGING; 184#else 185#define PHOSPHOR 0.0 186#define VSCANLINES 0.0 187#define InputGamma 2.2 188#define OutputGamma 2.2 189#define SHARPNESS 2.0 190#define COLOR_BOOST 1.3 191#define RED_BOOST 1.0 192#define GREEN_BOOST 1.0 193#define BLUE_BOOST 1.0 194#define SCANLINES_STRENGTH 1.0 195#define BEAM_MIN_WIDTH 0.60 196#define BEAM_MAX_WIDTH 0.80 197#define CRT_ANTI_RINGING 0.8 198#endif 199 200// Change these params to configure the horizontal filter. 201float B = 0.0; 202float C = 0.5; 203 204mat4 invX = mat4( 205 (-B - 6.0*C)/6.0, (3.0*B + 12.0*C)/6.0, (-3.0*B - 6.0*C)/6.0, B/6.0, 206 (12.0 - 9.0*B - 6.0*C)/6.0, (-18.0 + 12.0*B + 6.0*C)/6.0, 0.0, (6.0 - 2.0*B)/6.0, 207 -(12.0 - 9.0*B - 6.0*C)/6.0, (18.0 - 15.0*B - 12.0*C)/6.0, (3.0*B + 6.0*C)/6.0, B/6.0, 208 (B + 6.0*C)/6.0, -C, 0.0, 0.0 209); 210 211void main() 212{ 213 vec3 color; 214 215 vec2 TexSize = vec2(SHARPNESS*SourceSize.x, SourceSize.y); 216 217 vec2 dx = mix(vec2(1.0/TexSize.x, 0.0), vec2(0.0, 1.0/TexSize.y), VSCANLINES); 218 vec2 dy = mix(vec2(0.0, 1.0/TexSize.y), vec2(1.0/TexSize.x, 0.0), VSCANLINES); 219 220 vec2 pix_coord = vTexCoord*TexSize + vec2(-0.5, 0.5); 221 222 vec2 tc = mix((floor(pix_coord) + vec2(0.5, 0.5))/TexSize, (floor(pix_coord) + vec2(1.0, -0.5))/TexSize, VSCANLINES); 223 224 vec2 fp = mix(fract(pix_coord), fract(pix_coord.yx), VSCANLINES); 225 226 vec3 c00 = GAMMA_IN(COMPAT_TEXTURE(Source, tc - dx - dy).xyz); 227 vec3 c01 = GAMMA_IN(COMPAT_TEXTURE(Source, tc - dy).xyz); 228 vec3 c02 = GAMMA_IN(COMPAT_TEXTURE(Source, tc + dx - dy).xyz); 229 vec3 c03 = GAMMA_IN(COMPAT_TEXTURE(Source, tc + 2.0*dx - dy).xyz); 230 vec3 c10 = GAMMA_IN(COMPAT_TEXTURE(Source, tc - dx ).xyz); 231 vec3 c11 = GAMMA_IN(COMPAT_TEXTURE(Source, tc ).xyz); 232 vec3 c12 = GAMMA_IN(COMPAT_TEXTURE(Source, tc + dx ).xyz); 233 vec3 c13 = GAMMA_IN(COMPAT_TEXTURE(Source, tc + 2.0*dx ).xyz); 234 235 // Get min/max samples 236 vec3 min_sample = min(min(c01, c11), min(c02, c12)); 237 vec3 max_sample = max(max(c01, c11), max(c02, c12)); 238 239 mat4x3 color_matrix0 = mat4x3(c00, c01, c02, c03); 240 mat4x3 color_matrix1 = mat4x3(c10, c11, c12, c13); 241 242 vec4 invX_Px = vec4(fp.x*fp.x*fp.x, fp.x*fp.x, fp.x, 1.0) * invX; 243 vec3 color0 = color_matrix0 * invX_Px; 244 vec3 color1 = color_matrix1 * invX_Px; 245 246 // Anti-ringing 247 vec3 aux = color0; 248 color0 = clamp(color0, min_sample, max_sample); 249 color0 = mix(aux, color0, CRT_ANTI_RINGING); 250 aux = color1; 251 color1 = clamp(color1, min_sample, max_sample); 252 color1 = mix(aux, color1, CRT_ANTI_RINGING); 253 254 float pos0 = fp.y; 255 float pos1 = 1 - fp.y; 256 257 vec3 lum0 = mix(vec3(BEAM_MIN_WIDTH), vec3(BEAM_MAX_WIDTH), color0); 258 vec3 lum1 = mix(vec3(BEAM_MIN_WIDTH), vec3(BEAM_MAX_WIDTH), color1); 259 260 vec3 d0 = clamp(pos0/(lum0 + 0.0000001), 0.0, 1.0); 261 vec3 d1 = clamp(pos1/(lum1 + 0.0000001), 0.0, 1.0); 262 263 d0 = exp(-10.0*SCANLINES_STRENGTH*d0*d0); 264 d1 = exp(-10.0*SCANLINES_STRENGTH*d1*d1); 265 266 color = clamp(color0*d0 + color1*d1, 0.0, 1.0); 267 268 color *= COLOR_BOOST*vec3(RED_BOOST, GREEN_BOOST, BLUE_BOOST); 269 270 float mod_factor = mix(vTexCoord.x * OutputSize.x, vTexCoord.y * OutputSize.y, VSCANLINES); 271 272 vec3 dotMaskWeights = mix( 273 vec3(1.0, 0.7, 1.0), 274 vec3(0.7, 1.0, 0.7), 275 floor(mod(mod_factor, 2.0)) 276 ); 277 278 color.rgb *= mix(vec3(1.0), dotMaskWeights, PHOSPHOR); 279 280 color = GAMMA_OUT(color); 281 282FragColor = vec4(color, 1.0); 283} 284#endif 285