#include <metal_stdlib>
using namespace metal;

// Shader Art Coding Introduction — kishimisu
// MSL port of shader_art_coding_introduction.vk.glsl.

struct ShadertoyUBO {
    float iTime;
    float2 iResolution;
};

struct PassthroughVOut {
    float4 pos [[position]];
    float2 uv;
};

static float3 palette(float t) {
    float3 a = float3(0.5, 0.5, 0.5);
    float3 b = float3(0.5, 0.5, 0.5);
    float3 c = float3(1.0, 1.0, 1.0);
    float3 d = float3(0.263, 0.416, 0.557);
    return a + b * cos(6.28318 * (c * t * d));
}

fragment float4 shader_art_coding_introduction_fs(PassthroughVOut in [[stage_in]],
                                                   constant ShadertoyUBO& U [[buffer(0)]]) {
    float2 fragCoord = in.uv * U.iResolution;
    float2 uv = (fragCoord * 2.0 - U.iResolution) / U.iResolution.y;
    float2 uv0 = uv;
    float3 finalColor = float3(0.0);

    for (float i = 0.0; i < 4.0; i++) {
        uv = fract(uv * 1.5) - 0.5;

        float d = length(uv) * exp(-length(uv0));

        float3 col = palette(length(uv0) + i * 0.4 + U.iTime * 0.4);

        d = sin(d * 8.0 + U.iTime) / 8.0;
        d = abs(d);
        d = pow(0.01 / d, 1.2);

        finalColor += col * d;
    }

    return float4(finalColor, 1.0);
}
