File: MasterShader.metal

package info (click to toggle)
sameboy 1.0.2%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 10,528 kB
  • sloc: ansic: 29,948; objc: 22,249; asm: 1,424; pascal: 1,373; makefile: 1,065; xml: 111
file content (101 lines) | stat: -rw-r--r-- 2,949 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <metal_stdlib>
#include <simd/simd.h>
#include <metal_math>

using namespace metal;

/* For GLSL compatibility */
typedef float2 vec2;
typedef float3 vec3;
typedef float4 vec4;
typedef texture2d<half> sampler2D;
#define equal(x, y) all((x) == (y))
#define inequal(x, y) any((x) != (y))
#define STATIC static
#define GAMMA (2.2)

typedef struct {
    float4 position [[position]];
    float2 texcoords;
} rasterizer_data;

// Vertex Function
vertex rasterizer_data vertex_shader(uint index [[ vertex_id ]],
                                     constant vector_float2 *vertices [[ buffer(0) ]])
{
    rasterizer_data out;

    out.position.xy = vertices[index].xy;
    out.position.z = 0.0;
    out.position.w = 1.0;
    out.texcoords = (vertices[index].xy + float2(1, 1)) / 2.0;

    return out;
}


static inline float4 texture(texture2d<half> texture, float2 pos)
{
    constexpr sampler texture_sampler;
    return pow(float4(texture.sample(texture_sampler, pos)), GAMMA);
}

__attribute__((unused)) static inline float4 texture_relative(texture2d<half> t, float2 pos, float2 offset)
{
    float2 input_resolution = float2(t.get_width(), t.get_height());
    float2 origin = (floor(pos * input_resolution)) + float2(0.5, 0.5);
    return texture(t, (origin + offset) / input_resolution);
}

#line 1
{filter}

#define BLEND_BIAS (1.0/3.0)

enum frame_blending_mode {
    DISABLED,
    SIMPLE,
    ACCURATE,
    ACCURATE_EVEN = ACCURATE,
    ACCURATE_ODD,
};

fragment float4 fragment_shader(rasterizer_data in [[stage_in]],
                                texture2d<half> image [[ texture(0) ]],
                                texture2d<half> previous_image [[ texture(1) ]],
                                constant enum frame_blending_mode *frame_blending_mode [[ buffer(0) ]],
                                constant float2 *output_resolution [[ buffer(1) ]])
{
    float2 input_resolution = float2(image.get_width(), image.get_height());

    in.texcoords.y = 1 - in.texcoords.y;
    float ratio;
    switch (*frame_blending_mode) {
        default:
        case DISABLED:
            return pow(scale(image, in.texcoords, input_resolution, *output_resolution), 1 / GAMMA);
        case SIMPLE:
            ratio = 0.5;
            break;
        case ACCURATE_EVEN:
            if (((int)(in.texcoords.y * input_resolution.y) & 1) == 0) {
                ratio = BLEND_BIAS;
            }
            else {
                ratio = 1 - BLEND_BIAS;
            }
            break;
        case ACCURATE_ODD:
            if (((int)(in.texcoords.y * input_resolution.y) & 1) == 0) {
                ratio = 1 - BLEND_BIAS;
            }
            else {
                ratio = BLEND_BIAS;
            }
            break;
    }
    
    return pow(mix(scale(image, in.texcoords, input_resolution, *output_resolution),
               scale(previous_image, in.texcoords, input_resolution, *output_resolution), ratio), 1 / GAMMA);
}