git.y1.nz

SameBoy

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

Shaders/MasterShader.metal

      1 #include <metal_stdlib>
      2 #include <simd/simd.h>
      3 #include <metal_math>
      4 
      5 using namespace metal;
      6 
      7 /* For GLSL compatibility */
      8 typedef float2 vec2;
      9 typedef float3 vec3;
     10 typedef float4 vec4;
     11 typedef texture2d<half> sampler2D;
     12 #define equal(x, y) all((x) == (y))
     13 #define inequal(x, y) any((x) != (y))
     14 #define STATIC static
     15 #define GAMMA (2.2)
     16 
     17 typedef struct {
     18     float4 position [[position]];
     19     float2 texcoords;
     20 } rasterizer_data;
     21 
     22 // Vertex Function
     23 vertex rasterizer_data vertex_shader(uint index [[ vertex_id ]],
     24                                      constant vector_float2 *vertices [[ buffer(0) ]])
     25 {
     26     rasterizer_data out;
     27 
     28     out.position.xy = vertices[index].xy;
     29     out.position.z = 0.0;
     30     out.position.w = 1.0;
     31     out.texcoords = (vertices[index].xy + float2(1, 1)) / 2.0;
     32 
     33     return out;
     34 }
     35 
     36 
     37 static inline float4 texture(texture2d<half> texture, float2 pos)
     38 {
     39     constexpr sampler texture_sampler;
     40     return pow(float4(texture.sample(texture_sampler, pos)), GAMMA);
     41 }
     42 
     43 __attribute__((unused)) static inline float4 texture_relative(texture2d<half> t, float2 pos, float2 offset)
     44 {
     45     float2 input_resolution = float2(t.get_width(), t.get_height());
     46     float2 origin = (floor(pos * input_resolution)) + float2(0.5, 0.5);
     47     return texture(t, (origin + offset) / input_resolution);
     48 }
     49 
     50 #line 1
     51 {filter}
     52 
     53 #define BLEND_BIAS (1.0/3.0)
     54 
     55 enum frame_blending_mode {
     56     DISABLED,
     57     SIMPLE,
     58     ACCURATE,
     59     ACCURATE_EVEN = ACCURATE,
     60     ACCURATE_ODD,
     61 };
     62 
     63 fragment float4 fragment_shader(rasterizer_data in [[stage_in]],
     64                                 texture2d<half> image [[ texture(0) ]],
     65                                 texture2d<half> previous_image [[ texture(1) ]],
     66                                 constant enum frame_blending_mode *frame_blending_mode [[ buffer(0) ]],
     67                                 constant float2 *output_resolution [[ buffer(1) ]])
     68 {
     69     float2 input_resolution = float2(image.get_width(), image.get_height());
     70 
     71     in.texcoords.y = 1 - in.texcoords.y;
     72     float ratio;
     73     switch (*frame_blending_mode) {
     74         default:
     75         case DISABLED:
     76             return pow(scale(image, in.texcoords, input_resolution, *output_resolution), 1 / GAMMA);
     77         case SIMPLE:
     78             ratio = 0.5;
     79             break;
     80         case ACCURATE_EVEN:
     81             if (((int)(in.texcoords.y * input_resolution.y) & 1) == 0) {
     82                 ratio = BLEND_BIAS;
     83             }
     84             else {
     85                 ratio = 1 - BLEND_BIAS;
     86             }
     87             break;
     88         case ACCURATE_ODD:
     89             if (((int)(in.texcoords.y * input_resolution.y) & 1) == 0) {
     90                 ratio = 1 - BLEND_BIAS;
     91             }
     92             else {
     93                 ratio = BLEND_BIAS;
     94             }
     95             break;
     96     }
     97     
     98     return pow(mix(scale(image, in.texcoords, input_resolution, *output_resolution),
     99                scale(previous_image, in.texcoords, input_resolution, *output_resolution), ratio), 1 / GAMMA);
    100 }
    101 

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