Advertisement
Guest User

CRTGeom

a guest
Mar 30th, 2017
346
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.71 KB | None | 0 0
  1. #include "ReShade.fxh"
  2.  
  3. /* COMPATIBILITY
  4. - HLSL compilers
  5. - Cg compilers
  6. */
  7.  
  8. /*
  9. CRT-interlaced
  10.  
  11. Copyright (C) 2010-2012 cgwg, Themaister and DOLLS
  12.  
  13. This program is free software; you can redistribute it and/or modify it
  14. under the terms of the GNU General Public License as published by the Free
  15. Software Foundation; either version 2 of the License, or (at your option)
  16. any later version.
  17.  
  18. (cgwg gave their consent to have the original version of this shader
  19. distributed under the GPL in this message:
  20.  
  21. http://board.byuu.org/viewtopic.php?p=26075#p26075
  22.  
  23. "Feel free to distribute my shaders under the GPL. After all, the
  24. barrel distortion code was taken from the Curvature shader, which is
  25. under the GPL."
  26. )
  27. This shader variant is pre-configured with screen curvature
  28. */
  29.  
  30. uniform float texture_sizeX <
  31. ui_type = "drag";
  32. ui_min = 1.0;
  33. ui_max = BUFFER_WIDTH;
  34. ui_label = "Screen Width [CRT-Geom]";
  35. > = 320.0;
  36.  
  37. uniform float texture_sizeY <
  38. ui_type = "drag";
  39. ui_min = 1.0;
  40. ui_max = BUFFER_HEIGHT;
  41. ui_label = "Screen Height [CRT-Geom]";
  42. > = 240.0;
  43.  
  44. uniform float CRTgamma <
  45. ui_type = "drag";
  46. ui_min = 0.1;
  47. ui_max = 5.0;
  48. ui_step = 0.1;
  49. ui_label = "Target Gamma [CRT-Geom]";
  50. > = 2.4;
  51.  
  52. uniform float monitorgamma <
  53. ui_type = "drag";
  54. ui_min = 0.1;
  55. ui_max = 5.0;
  56. ui_step = 0.1;
  57. ui_label = "Monitor Gamma [CRT-Geom]";
  58. > = 2.2;
  59.  
  60. uniform float d <
  61. ui_type = "drag";
  62. ui_min = 0.1;
  63. ui_max = 3.0;
  64. ui_step = 0.1;
  65. ui_label = "Distance [CRT-Geom]";
  66. > = 1.5;
  67.  
  68. uniform float CURVATURE <
  69. ui_type = "drag";
  70. ui_min = 0.0;
  71. ui_max = 1.0;
  72. ui_step = 1.0;
  73. ui_label = "Curvature Toggle [CRT-Geom]";
  74. > = 1.0;
  75.  
  76. uniform float R <
  77. ui_type = "drag";
  78. ui_min = 0.0;
  79. ui_max = 10.0;
  80. ui_step = 0.1;
  81. ui_label = "Curvature Radius [CRT-Geom]";
  82. > = 2.0;
  83.  
  84. uniform float cornersize <
  85. ui_type = "drag";
  86. ui_min = 0.001;
  87. ui_max = 1.0;
  88. ui_step = 0.005;
  89. ui_label = "Corner Size [CRT-Geom]";
  90. > = 0.03;
  91.  
  92. uniform float cornersmooth <
  93. ui_type = "drag";
  94. ui_min = 80.0;
  95. ui_max = 2000.0;
  96. ui_step = 100.0;
  97. ui_label = "Corner Smoothness [CRT-Geom]";
  98. > = 1000.0;
  99.  
  100. uniform float x_tilt <
  101. ui_type = "drag";
  102. ui_min = -0.5;
  103. ui_max = 0.5;
  104. ui_step = 0.05;
  105. ui_label = "Horizontal Tilt [CRT-Geom]";
  106. > = 0.0;
  107.  
  108. uniform float y_tilt <
  109. ui_type = "drag";
  110. ui_min = -0.5;
  111. ui_max = 0.5;
  112. ui_step = 0.05;
  113. ui_label = "Vertical Tilt [CRT-Geom]";
  114. > = 0.0;
  115.  
  116. uniform float overscan_x <
  117. ui_type = "drag";
  118. ui_min = -125.0;
  119. ui_max = 125.0;
  120. ui_step = 1.0;
  121. ui_label = "Horiz. Overscan % [CRT-Geom]";
  122. > = 100.0;
  123.  
  124. uniform float overscan_y <
  125. ui_type = "drag";
  126. ui_min = -125.0;
  127. ui_max = 125.0;
  128. ui_step = 1.0;
  129. ui_label = "Vert. Overscan % [CRT-Geom]";
  130. > = 100.0;
  131.  
  132. uniform float DOTMASK <
  133. ui_type = "drag";
  134. ui_min = 0.0;
  135. ui_max = 0.3;
  136. ui_step = 0.3;
  137. ui_label = "Dot Mask Toggle [CRT-Geom]";
  138. > = 0.3;
  139.  
  140. uniform float SHARPER <
  141. ui_type = "drag";
  142. ui_min = 1.0;
  143. ui_max = 3.0;
  144. ui_step = 1.0;
  145. ui_label = "Sharpness [CRT-Geom]";
  146. > = 1.0;
  147.  
  148. uniform float scanline_weight <
  149. ui_type = "drag";
  150. ui_min = 0.1;
  151. ui_max = 0.5;
  152. ui_step = 0.01;
  153. ui_label = "Scanline Weight [CRT-Geom]";
  154. > = 0.3;
  155.  
  156. uniform float lum <
  157. ui_type = "drag";
  158. ui_min = 0.0;
  159. ui_max = 1.0;
  160. ui_step = 0.01;
  161. ui_label = "Luminance Boost [CRT-Geom]";
  162. > = 0.0;
  163.  
  164. uniform float interlace_toggle <
  165. ui_type = "drag";
  166. ui_min = 1.0;
  167. ui_max = 5.0;
  168. ui_step = 4.0;
  169. ui_label = "Interlacing [CRT-Geom]";
  170. > = 1.0;
  171.  
  172. uniform bool OVERSAMPLE <
  173. ui_tooltip = "Enable 3x oversampling of the beam profile; improves moire effect caused by scanlines+curvature";
  174. > = true;
  175.  
  176. uniform bool INTERLACED <
  177. ui_tooltip = "Use interlacing detection; may interfere with other shaders if combined";
  178. > = true;
  179.  
  180. #define FIX(c) max(abs(c), 1e-5);
  181. #define PI 3.141592653589
  182.  
  183. #define TEX2D(c) pow(tex2D(ReShade::BackBuffer, (c)), float4(CRTgamma,CRTgamma,CRTgamma,CRTgamma))
  184.  
  185. static const float2 aspect = float2(1.0, 0.75);
  186.  
  187. uniform int framecount < source = "framecount"; >;
  188.  
  189. float fmod(float a, float b)
  190. {
  191. float c = frac(abs(a/b))*abs(b);
  192. return (a < 0) ? -c : c; /* if ( a < 0 ) c = 0-c */
  193. }
  194.  
  195. float intersect(float2 xy, float2 sinangle, float2 cosangle)
  196. {
  197. float A = dot(xy,xy)+d*d;
  198. float B = 2.0*(R*(dot(xy,sinangle)-d*cosangle.x*cosangle.y)-d*d);
  199. float C = d*d + 2.0*R*d*cosangle.x*cosangle.y;
  200. return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
  201. }
  202.  
  203. float2 bkwtrans(float2 xy, float2 sinangle, float2 cosangle)
  204. {
  205. float c = intersect(xy, sinangle, cosangle);
  206. float2 pnt = float2(c,c)*xy;
  207. pnt -= float2(-R,-R)*sinangle;
  208. pnt /= float2(R,R);
  209. float2 tang = sinangle/cosangle;
  210. float2 poc = pnt/cosangle;
  211. float A = dot(tang,tang)+1.0;
  212. float B = -2.0*dot(poc,tang);
  213. float C = dot(poc,poc)-1.0;
  214. float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
  215. float2 uv = (pnt-a*sinangle)/cosangle;
  216. float r = FIX(R*acos(a));
  217. return uv*r/sin(r/R);
  218. }
  219.  
  220. float2 fwtrans(float2 uv, float2 sinangle, float2 cosangle)
  221. {
  222. float r = FIX(sqrt(dot(uv,uv)));
  223. uv *= sin(r/R)/r;
  224. float x = 1.0-cos(r/R);
  225. float D = d/R + x*cosangle.x*cosangle.y+dot(uv,sinangle);
  226. return d*(uv*cosangle-x*sinangle)/D;
  227. }
  228.  
  229. float3 maxscale(float2 sinangle, float2 cosangle)
  230. {
  231. float2 c = bkwtrans(-R * sinangle / (1.0 + R/d*cosangle.x*cosangle.y), sinangle, cosangle);
  232. float2 a = float2(0.5,0.5)*aspect;
  233. float2 lo = float2(fwtrans(float2(-a.x,c.y), sinangle, cosangle).x,
  234. fwtrans(float2(c.x,-a.y), sinangle, cosangle).y)/aspect;
  235. float2 hi = float2(fwtrans(float2(+a.x,c.y), sinangle, cosangle).x,
  236. fwtrans(float2(c.x,+a.y), sinangle, cosangle).y)/aspect;
  237. return float3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y));
  238. }
  239.  
  240. float4 scanlineWeights(float distance, float4 color)
  241. {
  242. // "wid" controls the width of the scanline beam, for each RGB
  243. // channel The "weights" lines basically specify the formula
  244. // that gives you the profile of the beam, i.e. the intensity as
  245. // a function of distance from the vertical center of the
  246. // scanline. In this case, it is gaussian if width=2, and
  247. // becomes nongaussian for larger widths. Ideally this should
  248. // be normalized so that the integral across the beam is
  249. // independent of its width. That is, for a narrower beam
  250. // "weights" should have a higher peak at the center of the
  251. // scanline than for a wider beam.
  252. float4 wid = 2.0 + 2.0 * pow(color, float4(4.0,4.0,4.0,4.0));
  253. float weights = float(distance / scanline_weight);
  254. return (lum + 1.4) * exp(-pow(weights * rsqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
  255. }
  256.  
  257. float4 PS_CRTGeom(float4 vpos : SV_Position, float2 uv : TexCoord) : SV_Target
  258. {
  259.  
  260. float2 TextureSize = float2(SHARPER * texture_sizeX, texture_sizeY);
  261. float mod_factor = uv.x * texture_sizeX * ReShade::ScreenSize.x / texture_sizeX;
  262. float2 ilfac = float2(1.0,clamp(floor(texture_sizeY/(200.0 * interlace_toggle)),1.0,2.0));
  263. float2 sinangle = sin(float2(x_tilt, y_tilt));
  264. float2 cosangle = cos(float2(x_tilt, y_tilt));
  265. float3 stretch = maxscale(sinangle, cosangle);
  266. float2 one = ilfac / TextureSize;
  267.  
  268. // Here's a helpful diagram to keep in mind while trying to
  269. // understand the code:
  270. //
  271. // | | | | |
  272. // -------------------------------
  273. // | | | | |
  274. // | 01 | 11 | 21 | 31 | <-- current scanline
  275. // | | @ | | |
  276. // -------------------------------
  277. // | | | | |
  278. // | 02 | 12 | 22 | 32 | <-- next scanline
  279. // | | | | |
  280. // -------------------------------
  281. // | | | | |
  282. //
  283. // Each character-cell represents a pixel on the output
  284. // surface, "@" represents the current pixel (always somewhere
  285. // in the bottom half of the current scan-line, or the top-half
  286. // of the next scanline). The grid of lines represents the
  287. // edges of the texels of the underlying texture.
  288.  
  289. // Texture coordinates of the texel containing the active pixel.
  290. float2 xy = 0.0;
  291. if (CURVATURE > 0.5){
  292. float2 cd = uv;
  293. cd *= float2(texture_sizeX,texture_sizeY) / float2(texture_sizeX,texture_sizeY);
  294. cd = (cd-float2(0.5,0.5))*aspect*stretch.z+stretch.xy;
  295. xy = (bkwtrans(cd, sinangle, cosangle)/float2(overscan_x / 100.0, overscan_y / 100.0)/aspect+float2(0.5,0.5)) * float2(texture_sizeX,texture_sizeY) / float2(texture_sizeX,texture_sizeY);
  296. } else {
  297. xy = uv;
  298. }
  299.  
  300. float2 cd2 = xy;
  301. cd2 *= float2(texture_sizeX,texture_sizeY) / float2(texture_sizeX,texture_sizeY);
  302. cd2 = (cd2 - float2(0.5,0.5)) * float2(overscan_x / 100.0, overscan_y / 100.0) + float2(0.5,0.5);
  303. cd2 = min(cd2, float2(1.0,1.0)-cd2) * aspect;
  304. float2 cdist = float2(cornersize,cornersize);
  305. cd2 = (cdist - min(cd2,cdist));
  306. float dist = sqrt(dot(cd2,cd2));
  307. float cval = clamp((cdist.x-dist)*cornersmooth,0.0, 1.0);
  308.  
  309. float2 xy2 = ((xy*TextureSize/float2(texture_sizeX,texture_sizeY)-float2(0.5,0.5))*float2(1.0,1.0)+float2(0.5,0.5))*float2(texture_sizeX,texture_sizeY)/TextureSize;
  310. // Of all the pixels that are mapped onto the texel we are
  311. // currently rendering, which pixel are we currently rendering?
  312. float2 ilfloat = float2(0.0,ilfac.y > 1.5 ? fmod(float(framecount),2.0) : 0.0);
  313.  
  314. float2 ratio_scale = (xy * TextureSize - float2(0.5,0.5) + ilfloat)/ilfac;
  315.  
  316. float filter = float2(texture_sizeX,texture_sizeY).y / ReShade::ScreenSize.y;
  317. float2 uv_ratio = frac(ratio_scale);
  318.  
  319. // Snap to the center of the underlying texel.
  320.  
  321. xy = (floor(ratio_scale)*ilfac + float2(0.5,0.5) - ilfloat) / TextureSize;
  322.  
  323. // Calculate Lanczos scaling coefficients describing the effect
  324. // of various neighbour texels in a scanline on the current
  325. // pixel.
  326. float4 coeffs = PI * float4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x);
  327.  
  328. // Prevent division by zero.
  329. coeffs = FIX(coeffs);
  330.  
  331. // Lanczos2 kernel.
  332. coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
  333.  
  334. // Normalize.
  335. coeffs /= dot(coeffs, float4(1.0,1.0,1.0,1.0));
  336.  
  337. // Calculate the effective colour of the current and next
  338. // scanlines at the horizontal location of the current pixel,
  339. // using the Lanczos coefficients above.
  340. float4 col = clamp(mul(coeffs, float4x4(
  341. TEX2D(xy + float2(-one.x, 0.0)),
  342. TEX2D(xy),
  343. TEX2D(xy + float2(one.x, 0.0)),
  344. TEX2D(xy + float2(2.0 * one.x, 0.0)))),
  345. 0.0, 1.0);
  346.  
  347. float4 col2 = clamp(mul(coeffs, float4x4(
  348. TEX2D(xy + float2(-one.x, one.y)),
  349. TEX2D(xy + float2(0.0, one.y)),
  350. TEX2D(xy + one),
  351. TEX2D(xy + float2(2.0 * one.x, one.y)))),
  352. 0.0, 1.0);
  353.  
  354. // Calculate the influence of the current and next scanlines on
  355. // the current pixel.
  356. float4 weights = scanlineWeights(uv_ratio.y, col);
  357. float4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);
  358.  
  359. if (OVERSAMPLE){
  360. uv_ratio.y =uv_ratio.y+1.0/3.0*filter;
  361. weights = (weights+scanlineWeights(uv_ratio.y, col))/3.0;
  362. weights2=(weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2))/3.0;
  363. uv_ratio.y =uv_ratio.y-2.0/3.0*filter;
  364. weights=weights+scanlineWeights(abs(uv_ratio.y), col)/3.0;
  365. weights2=weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2)/3.0;
  366. }
  367. float3 mul_res = (col * weights + col2 * weights2).rgb;
  368. mul_res *= float3(cval,cval,cval);
  369.  
  370. // dot-mask emulation:
  371. // Output pixels are alternately tinted green and magenta.
  372. float3 dotMaskWeights = lerp(
  373. float3(1.0, 1.0 - DOTMASK, 1.0),
  374. float3(1.0 - DOTMASK, 1.0, 1.0 - DOTMASK),
  375. floor(fmod(mod_factor, 2.0))
  376. );
  377. mul_res *= dotMaskWeights;
  378.  
  379.  
  380. // Convert the image gamma for display on our output device.
  381. mul_res = pow(mul_res, float3(1.0 / monitorgamma,1.0 / monitorgamma,1.0 / monitorgamma));
  382.  
  383. // Color the texel.
  384. return float4(mul_res, 1.0);
  385. }
  386.  
  387. technique GeomCRT {
  388. pass CRT_Geom {
  389. VertexShader=PostProcessVS;
  390. PixelShader=PS_CRTGeom;
  391. }
  392. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement