282 lines
9.1 KiB
Metal
282 lines
9.1 KiB
Metal
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
|
|
|
#include <metal_stdlib>
|
|
#include <simd/simd.h>
|
|
|
|
using namespace metal;
|
|
|
|
// Implementation of the GLSL mod() function, which is slightly different than Metal fmod()
|
|
template<typename Tx, typename Ty>
|
|
inline Tx mod(Tx x, Ty y)
|
|
{
|
|
return x - y * floor(x / y);
|
|
}
|
|
|
|
struct main0_out
|
|
{
|
|
float4 out_color [[color(0)]];
|
|
};
|
|
|
|
struct main0_in
|
|
{
|
|
float4 f_color [[user(locn0)]];
|
|
float2 f_local_or_uv [[user(locn1)]];
|
|
float4 f_params [[user(locn2)]];
|
|
float4 f_params2 [[user(locn3)]];
|
|
uint f_kind_flags [[user(locn4)]];
|
|
};
|
|
|
|
static inline __attribute__((always_inline))
|
|
float sdRoundedBox(thread const float2& p, thread const float2& b, thread float4& r)
|
|
{
|
|
float2 _56;
|
|
if (p.x > 0.0)
|
|
{
|
|
_56 = r.xy;
|
|
}
|
|
else
|
|
{
|
|
_56 = r.zw;
|
|
}
|
|
r.x = _56.x;
|
|
r.y = _56.y;
|
|
float _73;
|
|
if (p.y > 0.0)
|
|
{
|
|
_73 = r.x;
|
|
}
|
|
else
|
|
{
|
|
_73 = r.y;
|
|
}
|
|
r.x = _73;
|
|
float2 q = (abs(p) - b) + float2(r.x);
|
|
return (fast::min(fast::max(q.x, q.y), 0.0) + length(fast::max(q, float2(0.0)))) - r.x;
|
|
}
|
|
|
|
static inline __attribute__((always_inline))
|
|
float sdf_stroke(thread const float& d, thread const float& stroke_width)
|
|
{
|
|
return abs(d) - (stroke_width * 0.5);
|
|
}
|
|
|
|
static inline __attribute__((always_inline))
|
|
float sdCircle(thread const float2& p, thread const float& r)
|
|
{
|
|
return length(p) - r;
|
|
}
|
|
|
|
static inline __attribute__((always_inline))
|
|
float sdEllipse(thread float2& p, thread float2& ab)
|
|
{
|
|
p = abs(p);
|
|
if (p.x > p.y)
|
|
{
|
|
p = p.yx;
|
|
ab = ab.yx;
|
|
}
|
|
float l = (ab.y * ab.y) - (ab.x * ab.x);
|
|
float m = (ab.x * p.x) / l;
|
|
float m2 = m * m;
|
|
float n = (ab.y * p.y) / l;
|
|
float n2 = n * n;
|
|
float c = ((m2 + n2) - 1.0) / 3.0;
|
|
float c3 = (c * c) * c;
|
|
float q = c3 + ((m2 * n2) * 2.0);
|
|
float d = c3 + (m2 * n2);
|
|
float g = m + (m * n2);
|
|
float co;
|
|
if (d < 0.0)
|
|
{
|
|
float h = acos(q / c3) / 3.0;
|
|
float s = cos(h);
|
|
float t = sin(h) * 1.73205077648162841796875;
|
|
float rx = sqrt(((-c) * ((s + t) + 2.0)) + m2);
|
|
float ry = sqrt(((-c) * ((s - t) + 2.0)) + m2);
|
|
co = (((ry + (sign(l) * rx)) + (abs(g) / (rx * ry))) - m) / 2.0;
|
|
}
|
|
else
|
|
{
|
|
float h_1 = ((2.0 * m) * n) * sqrt(d);
|
|
float s_1 = sign(q + h_1) * powr(abs(q + h_1), 0.3333333432674407958984375);
|
|
float u = sign(q - h_1) * powr(abs(q - h_1), 0.3333333432674407958984375);
|
|
float rx_1 = (((-s_1) - u) - (c * 4.0)) + (2.0 * m2);
|
|
float ry_1 = (s_1 - u) * 1.73205077648162841796875;
|
|
float rm = sqrt((rx_1 * rx_1) + (ry_1 * ry_1));
|
|
co = (((ry_1 / sqrt(rm - rx_1)) + ((2.0 * g) / rm)) - m) / 2.0;
|
|
}
|
|
float2 r = ab * float2(co, sqrt(1.0 - (co * co)));
|
|
return length(r - p) * sign(p.y - r.y);
|
|
}
|
|
|
|
static inline __attribute__((always_inline))
|
|
float sdSegment(thread const float2& p, thread const float2& a, thread const float2& b)
|
|
{
|
|
float2 pa = p - a;
|
|
float2 ba = b - a;
|
|
float h = fast::clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
|
|
return length(pa - (ba * h));
|
|
}
|
|
|
|
static inline __attribute__((always_inline))
|
|
float sdf_alpha(thread const float& d, thread const float& soft)
|
|
{
|
|
return 1.0 - smoothstep(-soft, soft, d);
|
|
}
|
|
|
|
fragment main0_out main0(main0_in in [[stage_in]], texture2d<float> tex [[texture(0)]], sampler texSmplr [[sampler(0)]])
|
|
{
|
|
main0_out out = {};
|
|
uint kind = in.f_kind_flags & 255u;
|
|
uint flags = (in.f_kind_flags >> 8u) & 255u;
|
|
if (kind == 0u)
|
|
{
|
|
out.out_color = in.f_color * tex.sample(texSmplr, in.f_local_or_uv);
|
|
return out;
|
|
}
|
|
float d = 1000000015047466219876688855040.0;
|
|
float soft = 1.0;
|
|
if (kind == 1u)
|
|
{
|
|
float2 b = in.f_params.xy;
|
|
float4 r = float4(in.f_params.zw, in.f_params2.xy);
|
|
soft = fast::max(in.f_params2.z, 1.0);
|
|
float stroke_px = in.f_params2.w;
|
|
float2 param = in.f_local_or_uv;
|
|
float2 param_1 = b;
|
|
float4 param_2 = r;
|
|
float _453 = sdRoundedBox(param, param_1, param_2);
|
|
d = _453;
|
|
if ((flags & 1u) != 0u)
|
|
{
|
|
float param_3 = d;
|
|
float param_4 = stroke_px;
|
|
d = sdf_stroke(param_3, param_4);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (kind == 2u)
|
|
{
|
|
float radius = in.f_params.x;
|
|
soft = fast::max(in.f_params.y, 1.0);
|
|
float stroke_px_1 = in.f_params.z;
|
|
float2 param_5 = in.f_local_or_uv;
|
|
float param_6 = radius;
|
|
d = sdCircle(param_5, param_6);
|
|
if ((flags & 1u) != 0u)
|
|
{
|
|
float param_7 = d;
|
|
float param_8 = stroke_px_1;
|
|
d = sdf_stroke(param_7, param_8);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (kind == 3u)
|
|
{
|
|
float2 ab = in.f_params.xy;
|
|
soft = fast::max(in.f_params.z, 1.0);
|
|
float stroke_px_2 = in.f_params.w;
|
|
float2 param_9 = in.f_local_or_uv;
|
|
float2 param_10 = ab;
|
|
float _511 = sdEllipse(param_9, param_10);
|
|
d = _511;
|
|
if ((flags & 1u) != 0u)
|
|
{
|
|
float param_11 = d;
|
|
float param_12 = stroke_px_2;
|
|
d = sdf_stroke(param_11, param_12);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (kind == 4u)
|
|
{
|
|
float2 a = in.f_params.xy;
|
|
float2 b_1 = in.f_params.zw;
|
|
float width = in.f_params2.x;
|
|
soft = fast::max(in.f_params2.y, 1.0);
|
|
float2 param_13 = in.f_local_or_uv;
|
|
float2 param_14 = a;
|
|
float2 param_15 = b_1;
|
|
d = sdSegment(param_13, param_14, param_15) - (width * 0.5);
|
|
}
|
|
else
|
|
{
|
|
if (kind == 5u)
|
|
{
|
|
float inner = in.f_params.x;
|
|
float outer = in.f_params.y;
|
|
float start_rad = in.f_params.z;
|
|
float end_rad = in.f_params.w;
|
|
soft = fast::max(in.f_params2.x, 1.0);
|
|
float r_1 = length(in.f_local_or_uv);
|
|
float d_ring = fast::max(inner - r_1, r_1 - outer);
|
|
float angle = precise::atan2(in.f_local_or_uv.y, in.f_local_or_uv.x);
|
|
if (angle < 0.0)
|
|
{
|
|
angle += 6.283185482025146484375;
|
|
}
|
|
float ang_start = start_rad;
|
|
float ang_end = end_rad;
|
|
if (ang_start < 0.0)
|
|
{
|
|
ang_start += 6.283185482025146484375;
|
|
}
|
|
if (ang_end < 0.0)
|
|
{
|
|
ang_end += 6.283185482025146484375;
|
|
}
|
|
float _615;
|
|
if (ang_end > ang_start)
|
|
{
|
|
_615 = float((angle >= ang_start) && (angle <= ang_end));
|
|
}
|
|
else
|
|
{
|
|
_615 = float((angle >= ang_start) || (angle <= ang_end));
|
|
}
|
|
float in_arc = _615;
|
|
if (abs(ang_end - ang_start) >= 6.282185077667236328125)
|
|
{
|
|
in_arc = 1.0;
|
|
}
|
|
d = (in_arc > 0.5) ? d_ring : 1000000015047466219876688855040.0;
|
|
}
|
|
else
|
|
{
|
|
if (kind == 6u)
|
|
{
|
|
float radius_1 = in.f_params.x;
|
|
float rotation = in.f_params.y;
|
|
float sides = in.f_params.z;
|
|
soft = fast::max(in.f_params.w, 1.0);
|
|
float stroke_px_3 = in.f_params2.x;
|
|
float2 p = in.f_local_or_uv;
|
|
float c = cos(rotation);
|
|
float s = sin(rotation);
|
|
p = float2x2(float2(c, -s), float2(s, c)) * p;
|
|
float an = 3.1415927410125732421875 / sides;
|
|
float bn = mod(precise::atan2(p.y, p.x), 2.0 * an) - an;
|
|
d = (length(p) * cos(bn)) - radius_1;
|
|
if ((flags & 1u) != 0u)
|
|
{
|
|
float param_16 = d;
|
|
float param_17 = stroke_px_3;
|
|
d = sdf_stroke(param_16, param_17);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
float param_18 = d;
|
|
float param_19 = soft;
|
|
float alpha = sdf_alpha(param_18, param_19);
|
|
out.out_color = float4(in.f_color.xyz, in.f_color.w * alpha);
|
|
return out;
|
|
}
|
|
|