git.y1.nz

SameBoy

Accurate GB/GBC emulator
download: https://git.y1.nz/archives/sameboy.tar.gz
README | Files | Log | Refs | LICENSE

Shaders/CRT.fsh

      1 #define COLOR_LOW 0.45
      2 #define COLOR_HIGH 1.0
      3 #define VERTICAL_BORDER_DEPTH 0.6
      4 #define SCANLINE_DEPTH 0.55
      5 #define CURVENESS 0.3
      6 
      7 STATIC vec4 scale(sampler2D image, vec2 position, vec2 input_resolution, vec2 output_resolution)
      8 {
      9     /* Curve and pixel ratio */
     10     float y_curve = cos(position.x - 0.5) * CURVENESS + (1.0 - CURVENESS);
     11     float y_multiplier = 8.0 / 7.0 / y_curve;
     12     position.y *= y_multiplier;
     13     position.y -= (y_multiplier - 1.0) / 2.0;
     14     if (position.y < 0.0) return vec4(0,0,0,0);
     15     if (position.y > 1.0) return vec4(0,0,0,0);
     16     
     17     float x_curve = cos(position.y - 0.5) * CURVENESS + (1.0 - CURVENESS);
     18     float x_multiplier = 1.0/x_curve;
     19     position.x *= x_multiplier;
     20     position.x -= (x_multiplier - 1.0) / 2.0;
     21     if (position.x < 0.0) return vec4(0,0,0,0);
     22     if (position.x > 1.0) return vec4(0,0,0,0);
     23   
     24     /* Setting up common vars */
     25     vec2 pos = fract(position * input_resolution);
     26     vec2 sub_pos = pos * 6.0;
     27 
     28     vec4 center = texture_relative(image, position, vec2(0, 0));
     29     vec4 left = texture_relative(image, position, vec2(-1, 0));
     30     vec4 right = texture_relative(image, position, vec2(1, 0));
     31     
     32     /* Vertical blurring */
     33     if (sub_pos.y < 1.0) {
     34         center = mix(center, texture_relative(image, position, vec2( 0, -1)), 0.5 - sub_pos.y / 2.0);
     35         left =   mix(left,   texture_relative(image, position, vec2(-1, -1)), 0.5 - sub_pos.y / 2.0);
     36         right =  mix(right,  texture_relative(image, position, vec2( 1, -1)), 0.5 - sub_pos.y / 2.0);
     37     }
     38     else if (sub_pos.y > 5.0) {
     39         center = mix(center, texture_relative(image, position, vec2( 0, 1)), (sub_pos.y - 5.0) / 2.0);
     40         left =   mix(left,   texture_relative(image, position, vec2(-1, 1)), (sub_pos.y - 5.0) / 2.0);
     41         right =  mix(right,  texture_relative(image, position, vec2( 1, 1)), (sub_pos.y - 5.0) / 2.0);
     42     }
     43     
     44     /* Scanlines */
     45     float scanline_multiplier;
     46     if (pos.y < 0.5) {
     47         scanline_multiplier = (pos.y * 2.0) * SCANLINE_DEPTH + (1.0 - SCANLINE_DEPTH);
     48     }
     49     else  {
     50         scanline_multiplier = ((1.0 - pos.y) * 2.0) * SCANLINE_DEPTH + (1.0 - SCANLINE_DEPTH);
     51     }
     52     
     53     center *= scanline_multiplier;
     54     left *= scanline_multiplier;
     55     right *= scanline_multiplier;
     56 
     57     /* Vertical seperator for shadow masks */
     58     bool odd = bool(int((position * input_resolution).x) & 1);
     59     if (odd) {
     60         pos.y += 0.5;
     61         pos.y = fract(pos.y);
     62     }
     63     
     64     if (pos.y < 1.0 / 3.0) {
     65         float gradient_position = pos.y * 3.0;
     66         center *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
     67         left *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
     68         right *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
     69     }
     70     else if (pos.y > 2.0 / 3.0) {
     71         float gradient_position = (1.0 - pos.y) * 3.0;
     72         center *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
     73         left *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
     74         right *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
     75     }
     76 
     77     /* Blur the edges of the separators of adjacent columns */
     78     if (sub_pos.x < 1.0 || sub_pos.x > 5.0) {
     79         pos.y += 0.5;
     80         pos.y = fract(pos.y);
     81         
     82         if (pos.y < 1.0 / 3.0) {
     83             float gradient_position = pos.y * 3.0;
     84             if (pos.x < 0.5) {
     85                 gradient_position = 1.0 - (1.0 - gradient_position) * (1.0 - (pos.x) * 6.0);
     86             }
     87             else {
     88                 gradient_position = 1.0 - (1.0 - gradient_position) * (1.0 - (1.0 - pos.x) * 6.0);
     89             }
     90             center *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
     91             left *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
     92             right *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
     93         }
     94         else if (pos.y > 2.0 / 3.0) {
     95             float gradient_position = (1.0 - pos.y) * 3.0;
     96             if (pos.x < 0.5) {
     97                 gradient_position = 1.0 - (1.0 - gradient_position) * (1.0 - (pos.x) * 6.0);
     98             }
     99             else {
    100                 gradient_position = 1.0 - (1.0 - gradient_position) * (1.0 - (1.0 - pos.x) * 6.0);
    101             }
    102             center *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
    103             left *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
    104             right *= gradient_position * VERTICAL_BORDER_DEPTH + (1.0 - VERTICAL_BORDER_DEPTH);
    105         }
    106     }
    107 
    108     
    109     /* Subpixel blurring, like LCD filter*/
    110     
    111     vec4 midleft = mix(left, center, 0.5);
    112     vec4 midright = mix(right, center, 0.5);
    113     
    114     vec4 ret;
    115     if (sub_pos.x < 1.0) {
    116         ret = mix(vec4(COLOR_HIGH * center.r, COLOR_LOW * center.g, COLOR_HIGH * left.b, 1),
    117                   vec4(COLOR_HIGH * center.r, COLOR_LOW * center.g, COLOR_LOW  * left.b, 1),
    118                   sub_pos.x);
    119     }
    120     else if (sub_pos.x < 2.0) {
    121         ret = mix(vec4(COLOR_HIGH * center.r, COLOR_LOW  * center.g, COLOR_LOW * left.b, 1),
    122                   vec4(COLOR_HIGH * center.r, COLOR_HIGH * center.g, COLOR_LOW * midleft.b, 1),
    123                   sub_pos.x - 1.0);
    124     }
    125     else if (sub_pos.x < 3.0) {
    126         ret = mix(vec4(COLOR_HIGH * center.r  , COLOR_HIGH * center.g, COLOR_LOW * midleft.b, 1),
    127                   vec4(COLOR_LOW  * midright.r, COLOR_HIGH * center.g, COLOR_LOW * center.b, 1),
    128                   sub_pos.x - 2.0);
    129     }
    130     else if (sub_pos.x < 4.0) {
    131         ret = mix(vec4(COLOR_LOW * midright.r, COLOR_HIGH * center.g , COLOR_LOW  * center.b, 1),
    132                   vec4(COLOR_LOW * right.r   , COLOR_HIGH  * center.g, COLOR_HIGH * center.b, 1),
    133                   sub_pos.x - 3.0);
    134     }
    135     else if (sub_pos.x < 5.0) {
    136         ret = mix(vec4(COLOR_LOW * right.r, COLOR_HIGH * center.g  , COLOR_HIGH * center.b, 1),
    137                   vec4(COLOR_LOW * right.r, COLOR_LOW  * midright.g, COLOR_HIGH * center.b, 1),
    138                   sub_pos.x - 4.0);
    139     }
    140     else {
    141         ret = mix(vec4(COLOR_LOW  * right.r, COLOR_LOW * midright.g, COLOR_HIGH * center.b, 1),
    142                   vec4(COLOR_HIGH * right.r, COLOR_LOW * right.g  ,  COLOR_HIGH * center.b, 1),
    143                   sub_pos.x - 5.0);
    144     }
    145     
    146     /* Anti alias the curve */
    147     vec2 pixel_position = position * output_resolution;
    148     if (pixel_position.x < 1.0) {
    149         ret *= pixel_position.x;
    150     }
    151     else if (pixel_position.x > output_resolution.x - 1.0) {
    152         ret *= output_resolution.x - pixel_position.x;
    153     }
    154     if (pixel_position.y < 1.0) {
    155         ret *= pixel_position.y;
    156     }
    157     else if (pixel_position.y > output_resolution.y - 1.0) {
    158         ret *= output_resolution.y - pixel_position.y;
    159     }
    160     
    161     return ret;
    162 }

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.