git.y1.nz

SameBoy

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

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

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