// mosaic_transition — MSL, generated from https://github.com/gl-transitions/gl-transitions/blob/master/transitions/mosaic_transition.glsl
// Author: YueDev
// License: MIT
// Description: Both images break into mosaic blocks that blend, then sharpen into the incoming image
// Bindings and uniform layout: see the gl-transitions package README

// language: metal1.0
#include <metal_stdlib>
#include <simd/simd.h>

using metal::uint;

struct Uniforms {
    float progress;
    float ratio;
    float mosaicNum;
};

metal::float4 getToColor(
    thread metal::float2& uv,
    metal::sampler _sampler,
    metal::texture2d<float, metal::access::sample> _to
) {
    float _e16 = uv[0u];
    float _e18 = uv[1u];
    metal::float4 _e21 = _to.sample(_sampler, metal::float2(_e16, 1.0 - _e18), metal::level(0.0));
    return _e21;
}

metal::float4 getFromColor(
    thread metal::float2& uv_1,
    metal::texture2d<float, metal::access::sample> _from,
    metal::sampler _sampler
) {
    float _e16 = uv_1[0u];
    float _e18 = uv_1[1u];
    metal::float4 _e21 = _from.sample(_sampler, metal::float2(_e16, 1.0 - _e18), metal::level(0.0));
    return _e21;
}

metal::float2 getMosaicUV(
    thread metal::float2& uv_2,
    constant Uniforms& uniforms
) {
    float mosaicWidth = {};
    float mX = {};
    float mY = {};
    float _e19 = uniforms.mosaicNum;
    float _e22 = uniforms.progress;
    float _e24 = uniforms.progress;
    mosaicWidth = (2.0 / _e19) * metal::min(_e22, 1.0 - _e24);
    float _e29 = uv_2[0u];
    float _e30 = mosaicWidth;
    mX = metal::floor(_e29 / _e30) + 0.5;
    float _e35 = uv_2[1u];
    float _e36 = mosaicWidth;
    mY = metal::floor(_e35 / _e36) + 0.5;
    float _e40 = mX;
    float _e41 = mosaicWidth;
    float _e43 = mY;
    float _e44 = mosaicWidth;
    return metal::float2(_e40 * _e41, _e43 * _e44);
}

metal::float4 transition(
    thread metal::float2& uv_3,
    metal::texture2d<float, metal::access::sample> _from,
    metal::sampler _sampler,
    metal::texture2d<float, metal::access::sample> _to,
    constant Uniforms& uniforms
) {
    metal::float2 mosaicUV = {};
    metal::float2 local = {};
    metal::float2 param = {};
    metal::float2 param_1 = {};
    metal::float2 param_2 = {};
    float _e21 = uniforms.progress;
    float _e23 = uniforms.progress;
    if (metal::min(_e21, 1.0 - _e23) == 0.0) {
        metal::float2 _e27 = uv_3;
        local = _e27;
    } else {
        metal::float2 _e28 = uv_3;
        param = _e28;
        metal::float2 _e29 = getMosaicUV(param, uniforms);
        local = _e29;
    }
    metal::float2 _e30 = local;
    mosaicUV = _e30;
    metal::float2 _e31 = mosaicUV;
    param_1 = _e31;
    metal::float4 _e32 = getFromColor(param_1, _from, _sampler);
    metal::float2 _e33 = mosaicUV;
    param_2 = _e33;
    metal::float4 _e34 = getToColor(param_2, _sampler, _to);
    float _e36 = uniforms.progress;
    float _e38 = uniforms.progress;
    return metal::mix(_e32, _e34, metal::float4(_e36 * _e38));
}

void main_1(
    metal::texture2d<float, metal::access::sample> _from,
    metal::sampler _sampler,
    metal::texture2d<float, metal::access::sample> _to,
    constant Uniforms& uniforms,
    thread metal::float4& _fragColor,
    thread metal::float2& _uv_1
) {
    metal::float2 param_3 = {};
    metal::float2 _e15 = _uv_1;
    param_3 = _e15;
    metal::float4 _e16 = transition(param_3, _from, _sampler, _to, uniforms);
    _fragColor = _e16;
    return;
}

struct main_Input {
    metal::float2 _uv [[user(loc0), center_perspective]];
};
struct main_Output {
    metal::float4 member [[color(0)]];
};
fragment main_Output main_(
  main_Input varyings [[stage_in]]
, metal::texture2d<float, metal::access::sample> _from [[texture(0)]]
, metal::sampler _sampler [[sampler(0)]]
, metal::texture2d<float, metal::access::sample> _to [[texture(1)]]
, constant Uniforms& uniforms [[buffer(0)]]
) {
    metal::float4 _fragColor = {};
    metal::float2 _uv_1 = {};
    const auto _uv = varyings._uv;
    _uv_1 = _uv;
    main_1(_from, _sampler, _to, uniforms, _fragColor, _uv_1);
    metal::float4 _e3 = _fragColor;
    return main_Output { _e3 };
}
