SameBoy/Shaders/MasterShader.metal

95 lines
2.6 KiB
Metal
Raw Normal View History

#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;
2018-06-15 16:11:06 +00:00
typedef texture2d<half> sampler2D;
#define equal(x, y) all((x) == (y))
#define inequal(x, y) any((x) != (y))
#define STATIC static
2020-06-19 20:18:38 +00:00
#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;
2020-06-19 20:18:38 +00:00
return pow(float4(texture.sample(texture_sampler, pos)), GAMMA);
}
2018-06-15 16:11:06 +00:00
#line 1
{filter}
2018-06-15 15:44:22 +00:00
#define BLEND_BIAS (2.0/5.0)
2020-03-26 18:54:18 +00:00
enum frame_blending_mode {
DISABLED,
SIMPLE,
ACCURATE,
ACCURATE_EVEN = ACCURATE,
ACCURATE_ODD,
};
fragment float4 fragment_shader(rasterizer_data in [[stage_in]],
2018-06-15 10:58:50 +00:00
texture2d<half> image [[ texture(0) ]],
texture2d<half> previous_image [[ texture(1) ]],
2020-03-26 18:54:18 +00:00
constant enum frame_blending_mode *frame_blending_mode [[ buffer(0) ]],
2018-06-15 15:44:22 +00:00
constant float2 *output_resolution [[ buffer(1) ]])
{
float2 input_resolution = float2(image.get_width(), image.get_height());
in.texcoords.y = 1 - in.texcoords.y;
2020-03-26 18:54:18 +00:00
float ratio;
switch (*frame_blending_mode) {
default:
case DISABLED:
return pow(scale(image, in.texcoords, input_resolution, *output_resolution), 1 / GAMMA);
2020-03-26 18:54:18 +00:00
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;
2018-06-15 10:58:50 +00:00
}
2020-03-26 18:54:18 +00:00
2020-06-19 20:18:38 +00:00
return pow(mix(scale(image, in.texcoords, input_resolution, *output_resolution),
scale(previous_image, in.texcoords, input_resolution, *output_resolution), ratio), 1 / GAMMA);
}