Advertisement
Guest User

CRT-Geom GLSL

a guest
Jun 14th, 2013
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.87 KB | None | 0 0
  1. varying float CRTgamma;
  2. varying float monitorgamma;
  3. varying vec2 overscan;
  4. varying vec2 aspect;
  5. varying float d;
  6. varying float R;
  7. varying float cornersize;
  8. varying float cornersmooth;
  9.  
  10. varying vec3 stretch;
  11. varying vec2 sinangle;
  12. varying vec2 cosangle;
  13.  
  14. uniform vec2 InputSize;
  15. uniform vec2 TextureSize;
  16. uniform vec2 OutputSize;
  17.  
  18. varying vec2 tex;
  19. varying vec2 one;
  20. varying float mod_factor;
  21. varying vec2 ilfac;
  22.  
  23. #if defined(VERTEX)
  24.  
  25. attribute vec2 TexCoord;
  26. attribute vec2 VertexCoord;
  27. uniform mat4 MVPMatrix;
  28.  
  29. #define FIX(c) max(abs(c), 1e-5);
  30.  
  31. float intersect(vec2 xy)
  32. {
  33. float A = dot(xy,xy)+d*d;
  34. float B = 2.0*(R*(dot(xy,sinangle)-d*cosangle.x*cosangle.y)-d*d);
  35. float C = d*d + 2.0*R*d*cosangle.x*cosangle.y;
  36. return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
  37. }
  38.  
  39. vec2 bkwtrans(vec2 xy)
  40. {
  41. float c = intersect(xy);
  42. vec2 point = vec2(c)*xy;
  43. point -= vec2(-R)*sinangle;
  44. point /= vec2(R);
  45. vec2 tang = sinangle/cosangle;
  46. vec2 poc = point/cosangle;
  47. float A = dot(tang,tang)+1.0;
  48. float B = -2.0*dot(poc,tang);
  49. float C = dot(poc,poc)-1.0;
  50. float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
  51. vec2 uv = (point-a*sinangle)/cosangle;
  52. float r = R*acos(a);
  53. return uv*r/sin(r/R);
  54. }
  55.  
  56. vec2 fwtrans(vec2 uv)
  57. {
  58. float r = FIX(sqrt(dot(uv,uv)));
  59. uv *= sin(r/R)/r;
  60. float x = 1.0-cos(r/R);
  61. float D = d/R + x*cosangle.x*cosangle.y+dot(uv,sinangle);
  62. return d*(uv*cosangle-x*sinangle)/D;
  63. }
  64.  
  65. vec3 maxscale()
  66. {
  67. vec2 c = bkwtrans(-R * sinangle / (1.0 + R/d*cosangle.x*cosangle.y));
  68. vec2 a = vec2(0.5,0.5)*aspect;
  69. vec2 lo = vec2(fwtrans(vec2(-a.x,c.y)).x,
  70. fwtrans(vec2(c.x,-a.y)).y)/aspect;
  71. vec2 hi = vec2(fwtrans(vec2(+a.x,c.y)).x,
  72. fwtrans(vec2(c.x,+a.y)).y)/aspect;
  73. return vec3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y));
  74. }
  75.  
  76.  
  77. void main()
  78. {
  79.  
  80. // START of parameters
  81.  
  82. // gamma of simulated CRT
  83. CRTgamma = 2.2;
  84. // gamma of display monitor (typically 2.2 is correct)
  85. monitorgamma = 2.2;
  86. // overscan (e.g. 1.02 for 2% overscan)
  87. overscan = vec2(1.00,1.00);
  88. // aspect ratio
  89. aspect = vec2(1.0, 0.75);
  90. // lengths are measured in units of (approximately) the width of the monitor
  91. // simulated distance from viewer to monitor
  92. d = 2.0;
  93. // radius of curvature
  94. R = 1.5;
  95. // tilt angle in radians
  96. // (behavior might be a bit wrong if both components are nonzero)
  97. const vec2 angle = vec2(0.0,0.001);
  98. // size of curved corners
  99. cornersize = 0.001;
  100. // border smoothness parameter
  101. // decrease if borders are too aliased
  102. cornersmooth = 1000.0;
  103.  
  104. // END of parameters
  105.  
  106. // Do the standard vertex processing.
  107. gl_Position = MVPMatrix * vec4(VertexCoord, 0.0, 1.0);
  108.  
  109. // Precalculate a bunch of useful values we'll need in the fragment
  110. // shader.
  111. sinangle = sin(angle);
  112. cosangle = cos(angle);
  113. stretch = maxscale();
  114.  
  115. // Texture coords.
  116. tex = TexCoord;
  117.  
  118. ilfac = vec2(1.0,floor(InputSize.y/200.0));
  119.  
  120. // The size of one texel, in texture-coordinates.
  121. one = ilfac / TextureSize;
  122.  
  123. // Resulting X pixel-coordinate of the pixel we're drawing.
  124. mod_factor = tex.x * TextureSize.x * OutputSize.x / InputSize.x;
  125. }
  126.  
  127. #elif defined(FRAGMENT)
  128.  
  129. // Comment the next line to disable interpolation in linear gamma (and gain speed).
  130. #define LINEAR_PROCESSING
  131.  
  132. // Enable screen curvature.
  133. //#define CURVATURE
  134.  
  135. // Enable 3x oversampling of the beam profile
  136. #define OVERSAMPLE
  137.  
  138. // Use the older, purely gaussian beam profile
  139. //#define USEGAUSSIAN
  140.  
  141. // Macros.
  142. #define FIX(c) max(abs(c), 1e-5);
  143. #define PI 3.141592653589
  144.  
  145. #ifdef LINEAR_PROCESSING
  146. # define TEX2D(c) pow(texture2D(Texture, (c)), vec4(CRTgamma))
  147. #else
  148. # define TEX2D(c) texture2D(Texture, (c))
  149. #endif
  150.  
  151. uniform sampler2D Texture;
  152. uniform int FrameCount;
  153.  
  154. float intersect(vec2 xy)
  155. {
  156. float A = dot(xy,xy)+d*d;
  157. float B = 2.0*(R*(dot(xy,sinangle)-d*cosangle.x*cosangle.y)-d*d);
  158. float C = d*d + 2.0*R*d*cosangle.x*cosangle.y;
  159. return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
  160. }
  161.  
  162. vec2 bkwtrans(vec2 xy)
  163. {
  164. float c = intersect(xy);
  165. vec2 point = vec2(c)*xy;
  166. point -= vec2(-R)*sinangle;
  167. point /= vec2(R);
  168. vec2 tang = sinangle/cosangle;
  169. vec2 poc = point/cosangle;
  170. float A = dot(tang,tang)+1.0;
  171. float B = -2.0*dot(poc,tang);
  172. float C = dot(poc,poc)-1.0;
  173. float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
  174. vec2 uv = (point-a*sinangle)/cosangle;
  175. float r = FIX(R*acos(a));
  176. return uv*r/sin(r/R);
  177. }
  178.  
  179. vec2 transform(vec2 coord)
  180. {
  181. coord *= TextureSize / InputSize;
  182. coord = (coord-vec2(0.5))*aspect*stretch.z+stretch.xy;
  183. return (bkwtrans(coord)/overscan/aspect+vec2(0.5)) * InputSize / TextureSize;
  184. }
  185.  
  186. float corner(vec2 coord)
  187. {
  188. coord *= TextureSize / InputSize;
  189. coord = (coord - vec2(0.5)) * overscan + vec2(0.5);
  190. coord = min(coord, vec2(1.0)-coord) * aspect;
  191. vec2 cdist = vec2(cornersize);
  192. coord = (cdist - min(coord,cdist));
  193. float dist = sqrt(dot(coord,coord));
  194. return clamp((cdist.x-dist)*cornersmooth,0.0, 1.0);
  195. }
  196.  
  197. // Calculate the influence of a scanline on the current pixel.
  198. //
  199. // 'distance' is the distance in texture coordinates from the current
  200. // pixel to the scanline in question.
  201. // 'color' is the colour of the scanline at the horizontal location of
  202. // the current pixel.
  203. vec4 scanlineWeights(float distance, vec4 color)
  204. {
  205. // "wid" controls the width of the scanline beam, for each RGB channel
  206. // The "weights" lines basically specify the formula that gives
  207. // you the profile of the beam, i.e. the intensity as
  208. // a function of distance from the vertical center of the
  209. // scanline. In this case, it is gaussian if width=2, and
  210. // becomes nongaussian for larger widths. Ideally this should
  211. // be normalized so that the integral across the beam is
  212. // independent of its width. That is, for a narrower beam
  213. // "weights" should have a higher peak at the center of the
  214. // scanline than for a wider beam.
  215. #ifdef USEGAUSSIAN
  216. vec4 wid = 0.3 + 0.1 * pow(color, vec4(3.0));
  217. vec4 weights = vec4(distance / wid);
  218. return 0.4 * exp(-weights * weights) / wid;
  219. #else
  220. vec4 wid = 2.0 + 2.0 * pow(color, vec4(4.0));
  221. vec4 weights = vec4(distance / 0.4);
  222. return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
  223. #endif
  224. }
  225.  
  226. void main()
  227. {
  228. // Here's a helpful diagram to keep in mind while trying to
  229. // understand the code:
  230. //
  231. // | | | | |
  232. // -------------------------------
  233. // | | | | |
  234. // | 01 | 11 | 21 | 31 | <-- current scanline
  235. // | | @ | | |
  236. // -------------------------------
  237. // | | | | |
  238. // | 02 | 12 | 22 | 32 | <-- next scanline
  239. // | | | | |
  240. // -------------------------------
  241. // | | | | |
  242. //
  243. // Each character-cell represents a pixel on the output
  244. // surface, "@" represents the current pixel (always somewhere
  245. // in the bottom half of the current scan-line, or the top-half
  246. // of the next scanline). The grid of lines represents the
  247. // edges of the texels of the underlying texture.
  248.  
  249. // Texture coordinates of the texel containing the active pixel.
  250. #ifdef CURVATURE
  251. vec2 xy = transform(tex);
  252. #else
  253. vec2 xy = tex;
  254. #endif
  255. float cval = corner(xy);
  256.  
  257. // Of all the pixels that are mapped onto the texel we are
  258. // currently rendering, which pixel are we currently rendering?
  259. vec2 ilvec = vec2(0.0,ilfac.y > 1.5 ? mod(float(FrameCount),2.0) : 0.0);
  260. vec2 ratio_scale = (xy * TextureSize - vec2(0.5) + ilvec)/ilfac;
  261. #ifdef OVERSAMPLE
  262. float filter = fwidth(ratio_scale.y);
  263. #endif
  264. vec2 uv_ratio = fract(ratio_scale);
  265.  
  266. // Snap to the center of the underlying texel.
  267. xy = (floor(ratio_scale)*ilfac + vec2(0.5) - ilvec) / TextureSize;
  268.  
  269. // Calculate Lanczos scaling coefficients describing the effect
  270. // of various neighbour texels in a scanline on the current
  271. // pixel.
  272. vec4 coeffs = PI * vec4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x);
  273.  
  274. // Prevent division by zero.
  275. coeffs = FIX(coeffs);
  276.  
  277. // Lanczos2 kernel.
  278. coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
  279.  
  280. // Normalize.
  281. coeffs /= dot(coeffs, vec4(1.0));
  282.  
  283. // Calculate the effective colour of the current and next
  284. // scanlines at the horizontal location of the current pixel,
  285. // using the Lanczos coefficients above.
  286. vec4 col = clamp(mat4(
  287. TEX2D(xy + vec2(-one.x, 0.0)),
  288. TEX2D(xy),
  289. TEX2D(xy + vec2(one.x, 0.0)),
  290. TEX2D(xy + vec2(2.0 * one.x, 0.0))) * coeffs,
  291. 0.0, 1.0);
  292. vec4 col2 = clamp(mat4(
  293. TEX2D(xy + vec2(-one.x, one.y)),
  294. TEX2D(xy + vec2(0.0, one.y)),
  295. TEX2D(xy + one),
  296. TEX2D(xy + vec2(2.0 * one.x, one.y))) * coeffs,
  297. 0.0, 1.0);
  298.  
  299. #ifndef LINEAR_PROCESSING
  300. col = pow(col , vec4(CRTgamma));
  301. col2 = pow(col2, vec4(CRTgamma));
  302. #endif
  303.  
  304. // Calculate the influence of the current and next scanlines on
  305. // the current pixel.
  306. vec4 weights = scanlineWeights(uv_ratio.y, col);
  307. vec4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);
  308. #ifdef OVERSAMPLE
  309. uv_ratio.y =uv_ratio.y+1.0/3.0*filter;
  310. weights = (weights+scanlineWeights(uv_ratio.y, col))/3.0;
  311. weights2=(weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2))/3.0;
  312. uv_ratio.y =uv_ratio.y-2.0/3.0*filter;
  313. weights=weights+scanlineWeights(abs(uv_ratio.y), col)/3.0;
  314. weights2=weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2)/3.0;
  315. #endif
  316. vec3 mul_res = (col * weights + col2 * weights2).rgb * vec3(cval);
  317.  
  318. // dot-mask emulation:
  319. // Output pixels are alternately tinted green and magenta.
  320. vec3 dotMaskWeights = mix(
  321. vec3(1.0, 0.7, 1.0),
  322. vec3(0.7, 1.0, 0.7),
  323. floor(mod(mod_factor, 2.0))
  324. );
  325.  
  326. mul_res *= dotMaskWeights;
  327.  
  328. // Convert the image gamma for display on our output device.
  329. mul_res = pow(mul_res, vec3(1.0 / monitorgamma));
  330.  
  331. // Color the texel.
  332. gl_FragColor = vec4(mul_res, 1.0);
  333. }
  334. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement