Guest User

crt-geom-flat-sharp

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