Advertisement
Guest User

scanline.dsd

a guest
Dec 22nd, 2017
934
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Scanline shader
  2. // timothylottes.blogspot.com/2014/08/scanlines.html
  3. // https://www.shadertoy.com/view/XsjSzR#
  4. //
  5. // PUBLIC DOMAIN CRT STYLED SCAN-LINE SHADER
  6. //
  7. //   by Timothy Lottes
  8. //
  9. // This is more along the style of a really good CGA arcade monitor.
  10. // With RGB inputs instead of NTSC.
  11. // The shadow mask example has the mask rotated 90 degrees for less chromatic aberration.
  12. //
  13. // Left it unoptimized to show the theory behind the algorithm.
  14. //
  15. // It is an example what I personally would want as a display option for pixel art games.
  16. // Please take and use, change, or whatever.
  17. =============================================
  18.  
  19. <vertex>
  20. attribute vec2 a_vertex_coordinate;
  21. attribute vec2 a_texture_coordinate;
  22.  
  23. varying vec2 v_texture_coordinate;
  24. varying vec2 v_screen_coordinate;
  25. void main() {
  26.   gl_Position = vec4(a_vertex_coordinate.xy, 0.0, 1.0);
  27.   v_texture_coordinate = a_texture_coordinate;
  28.   v_screen_coordinate = a_texture_coordinate * u_target_size;
  29. }
  30. </vertex>
  31.  
  32. <fragment>
  33. // Optimize for resize.
  34. vec2 res;
  35.  
  36. // Hardness of scanline.
  37. //  -8.0 = soft
  38. // -16.0 = medium
  39. float hardScan=-8.0;
  40.  
  41. // Hardness of pixels in scanline.
  42. // -2.0 = soft
  43. // -4.0 = hard
  44. float hardPix=-3.0;
  45.  
  46. // Display warp.
  47. // 0.0 = none
  48. // 1.0/8.0 = extreme
  49. //vec2 warp=vec2(1.0/32.0,1.0/24.0);
  50. vec2 warp=vec2(0.0,0.0);
  51.  
  52. // Amount of shadow mask.
  53. float maskDark=0.5;
  54. float maskLight=1.5;
  55.  
  56. //------------------------------------------------------------------------
  57.  
  58. // sRGB to Linear.
  59. // Assuing using sRGB typed textures this should not be needed.
  60. float ToLinear1(float c){return(c<=0.04045)?c/12.92:pow((c+0.055)/1.055,2.4);}
  61. vec3 ToLinear(vec3 c){return vec3(ToLinear1(c.r),ToLinear1(c.g),ToLinear1(c.b));}
  62.  
  63. // Linear to sRGB.
  64. // Assuing using sRGB typed textures this should not be needed.
  65. float ToSrgb1(float c){return(c<0.0031308?c*12.92:1.055*pow(c,0.41666)-0.055);}
  66. vec3 ToSrgb(vec3 c){return vec3(ToSrgb1(c.r),ToSrgb1(c.g),ToSrgb1(c.b));}
  67.  
  68. // Nearest emulated sample given floating point position and texel offset.
  69. // Also zero's off screen.
  70. vec3 Fetch(sampler2D tex,vec2 pos,vec2 off){
  71.   pos=floor(pos*res+off)/res;
  72.   if(max(abs(pos.x-0.5),abs(pos.y-0.5))>0.5)return vec3(0.0,0.0,0.0);
  73.   return ToLinear(texture2D(tex,pos.xy,-16.0).rgb);}
  74.  
  75. // Distance in emulated pixels to nearest texel.
  76. vec2 Dist(vec2 pos){pos=pos*res;return -((pos-floor(pos))-vec2(0.5));}
  77.    
  78. // 1D Gaussian.
  79. float Gaus(float pos,float scale){return exp2(scale*pos*pos);}
  80.  
  81. // 3-tap Gaussian filter along horz line.
  82. vec3 Horz3(sampler2D tex,vec2 pos,float off){
  83.   vec3 b=Fetch(tex,pos,vec2(-1.0,off));
  84.   vec3 c=Fetch(tex,pos,vec2( 0.0,off));
  85.   vec3 d=Fetch(tex,pos,vec2( 1.0,off));
  86.   float dst=Dist(pos).x;
  87.   // Convert distance to weight.
  88.   float scale=hardPix;
  89.   float wb=Gaus(dst-1.0,scale);
  90.   float wc=Gaus(dst+0.0,scale);
  91.   float wd=Gaus(dst+1.0,scale);
  92.   // Return filtered sample.
  93.   return (b*wb+c*wc+d*wd)/(wb+wc+wd);}
  94.  
  95. // 5-tap Gaussian filter along horz line.
  96. vec3 Horz5(sampler2D tex,vec2 pos,float off){
  97.   vec3 a=Fetch(tex,pos,vec2(-2.0,off));
  98.   vec3 b=Fetch(tex,pos,vec2(-1.0,off));
  99.   vec3 c=Fetch(tex,pos,vec2( 0.0,off));
  100.   vec3 d=Fetch(tex,pos,vec2( 1.0,off));
  101.   vec3 e=Fetch(tex,pos,vec2( 2.0,off));
  102.   float dst=Dist(pos).x;
  103.   // Convert distance to weight.
  104.   float scale=hardPix;
  105.   float wa=Gaus(dst-2.0,scale);
  106.   float wb=Gaus(dst-1.0,scale);
  107.   float wc=Gaus(dst+0.0,scale);
  108.   float wd=Gaus(dst+1.0,scale);
  109.   float we=Gaus(dst+2.0,scale);
  110.   // Return filtered sample.
  111.   return (a*wa+b*wb+c*wc+d*wd+e*we)/(wa+wb+wc+wd+we);}
  112.  
  113. // Return scanline weight.
  114. float Scan(vec2 pos,float off){
  115.   float dst=Dist(pos).y;
  116.   return Gaus(dst+off,hardScan);}
  117.  
  118. // Allow nearest three lines to effect pixel.
  119. vec3 Tri(sampler2D tex,vec2 pos){
  120.   vec3 a=Horz3(tex,pos,-1.0);
  121.   vec3 b=Horz5(tex,pos, 0.0);
  122.   vec3 c=Horz3(tex,pos, 1.0);
  123.   float wa=Scan(pos,-1.0);
  124.   float wb=Scan(pos, 0.0);
  125.   float wc=Scan(pos, 1.0);
  126.   return a*wa+b*wb+c*wc;}
  127.  
  128. // Distortion of scanlines, and end of screen alpha.
  129. vec2 Warp(vec2 pos){
  130.   pos=pos*2.0-1.0;    
  131.   pos*=vec2(1.0+(pos.y*pos.y)*warp.x,1.0+(pos.x*pos.x)*warp.y);
  132.   return pos*0.5+0.5;}
  133.  
  134. // Shadow mask.
  135. vec3 Mask(vec2 pos){
  136.   pos.x+=pos.y*3.0;
  137.   vec3 mask=vec3(maskDark,maskDark,maskDark);
  138.   pos.x=fract(pos.x/6.0);
  139.   if(pos.x<0.333)mask.r=maskLight;
  140.   else if(pos.x<0.666)mask.g=maskLight;
  141.   else mask.b=maskLight;
  142.   return mask;}    
  143.  
  144. // Entry.
  145. varying vec2 v_texture_coordinate;
  146. varying vec2 v_screen_coordinate;
  147. uniform sampler2D u_texture;
  148.  
  149. void main(){
  150.   vec4 color = vec4(0.0, 0.0, 0.0, 1.0);
  151.   res=u_target_size.xy;
  152.   vec2 pos=Warp(v_screen_coordinate.xy/res);
  153.  
  154. //    hardScan=-12.0;
  155. //    maskDark=maskLight=1.0;
  156. //    pos=Warp(v_screen_coordinate.xy/res);
  157.  
  158.   color.rgb=Tri(u_texture,pos)*Mask(v_screen_coordinate.xy);
  159.  
  160.   color.rgb=ToSrgb(color.rgb);
  161.  
  162.   gl_FragColor = color;
  163. }
  164. </fragment>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement