{
  "name": "Swipe up (Vertical swipe)",
  "curve": "Cubic Out",
  "type": "fixed",
  "duration": 3.0,
  "passes": [
    {
      "name": "vertical swipe",
      "inputs": [
        "default"
      ],
      "glsl": "precision highp float;

               varying vec2 sourceTextureCoordinate;

               // default uniforms for all filters
               uniform vec2 outputSize; // size of the output fbo

               // default uniforms for transitions and video effects
               uniform float progress; // normalized 0-1

               // default uniforms for video effects
               uniform float duration; // in seconds

               const float T0  = 0.0;
               const float T1 = 0.17741935;
               const float T2 = 0.33870968;
               const float T3 = 0.5;
               const float T4 = 0.77419355;
               const float T5 = 1.0;

               const float Y0 = 567.0;
               const float Y1 = 440.7;
               const float Y2 = 391.0;
               const float Y3 = 322.0;
               const float Y4 = -456.6;
               const float Y5 = -569.0;


               float catmullRom(float p0, float p1, float p2, float p3, float t){
                 float t2 = t * t;
                 float t3 = t2 * t;
                 return 0.5 * (
                   2.0 * p1 +
                   (-p0 + p2) * t +
                   (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3) * t2 +
                   (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3
                 );
               }

               float getY(float p){
                 if (p < T1) {
                   float u = (p - T0) / (T1 - T0);
                   return catmullRom(Y0, Y0, Y1, Y2, u);
                 } else if (p < T2){
                   float u = (p - T1) / (T2 - T1);
                   return catmullRom(Y0, Y1, Y2, Y3, u);
                 } else if (p < T3){
                   float u = (p - T2) / (T3 - T2);
                   return catmullRom(Y1, Y2, Y3, Y4, u);
                 } else if (p < T4){
                   float u = (p - T3) / (T4 - T3);
                   return catmullRom(Y2, Y3, Y4, Y5, u);
                 } else {
                   float u = (p - T4) / (T5 - T4);
                   return catmullRom(Y3, Y4, Y5, Y5, u);
                 }
               }

               vec4 motionBlur(vec2 uv, float blurStrength){
                 float offset = (10.0 / outputSize.y) * blurStrength;
                 vec4 c0 = sampleInput(fract(uv + vec2(0.0, -offset)));
                 vec4 c1 = sampleInput(fract(uv));
                 vec4 c2 = sampleInput(fract(uv + vec2(0.0, offset)));
                 return (c0 + c1 + c2) / 3.0;
               }


               void main() {

                 vec2 uv = sourceTextureCoordinate;

                 float p = clamp(progress, 0.0, 1.0);
                 float yPx = getY(p);

                 float offsetY = 0.5 - (yPx / 1134.0);
                 uv.y += offsetY;

                float blurCurve = 1.0 - abs(progress - 0.5) * 2.0;
                 blurCurve = clamp(blurCurve, 0.0,1.0);

                 vec4 base = motionBlur(uv, blurCurve);
                 vec4 color = base;
                 gl_FragColor = toOutputFormat(color);
               }
",
  "metal": "
    using namespace metal;
    struct fragmentIn { float2 sourceTextureCoordinate [[user(locn1)]]; };
    struct fragmentOut { float4 _gl_FragColor [[color(0)]]; };
    typedef struct {
        float4x4 content_transform;
        float4x4 texture_transform;
        float strength;
        float progress;
        float time_sec;
        float duration_sec;
        float clip_duration_sec;
        float2 inputSize;
        float2 outputSize;
        float2 tex0Size;
    } Uniforms;

    constant float T0 = 0.0;
    constant float T1 = 0.17741935;
    constant float T2 = 0.33870968;
    constant float T3 = 0.5;
    constant float T4 = 0.77419355;
    constant float T5 = 1.0;

    constant float Y0 = 567.0;
    constant float Y1 = 440.7;
    constant float Y2 = 391.0;
    constant float Y3 = 322.0;
    constant float Y4 = -456.6;
    constant float Y5 = -569.0;

    float catmullRom(float p0, float p1, float p2, float p3, float t) {
        float t2 = t * t;
        float t3 = t2 * t;
        return 0.5 * (
            2.0 * p1 +
            (-p0 + p2) * t +
            (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3) * t2 +
            (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3
        );
    }

    float getY(float p) {
        if (p < T1) {
            float u = (p - T0) / (T1 - T0);
            return catmullRom(Y0, Y0, Y1, Y2, u);
        } else if (p < T2) {
            float u = (p - T1) / (T2 - T1);
            return catmullRom(Y0, Y1, Y2, Y3, u);
        } else if (p < T3) {
            float u = (p - T2) / (T3 - T2);
            return catmullRom(Y1, Y2, Y3, Y4, u);
        } else if (p < T4) {
            float u = (p - T3) / (T4 - T3);
            return catmullRom(Y2, Y3, Y4, Y5, u);
        } else {
            float u = (p - T4) / (T5 - T4);
            return catmullRom(Y3, Y4, Y5, Y5, u);
        }
    }

    float4 motionBlur(float2 uv, float blurStrength, DefaultInputs defaultInputs) {
        float offset = (10.0 / 1134.0) * blurStrength;
        float4 c0 = sampleInput(defaultInputs, fract(uv + float2(0.0, -offset)));
        float4 c1 = sampleInput(defaultInputs, fract(uv));
        float4 c2 = sampleInput(defaultInputs, fract(uv + float2(0.0, offset)));
        return (c0 + c1 + c2) / 3.0;
    }

    fragment fragmentOut fragmentShader(
        fragmentIn in [[stage_in]],
        constant Uniforms & uniforms [[buffer(1)]],
        DefaultInputs defaultInputs) {

        fragmentOut out = {};
        float2 uv = in.sourceTextureCoordinate;

        float p = clamp(uniforms.progress, 0.0, 1.0);
        float yPx = getY(p);

        float offsetY = 0.5 - (yPx / 1134.0);
        uv.y += offsetY;

        float blurCurve = 1.0 - abs(uniforms.progress - 0.5) * 2.0;
        blurCurve = clamp(blurCurve, 0.0, 1.0);

        float4 base = motionBlur(uv, blurCurve, defaultInputs);
        float4 color = base;
        out._gl_FragColor = color;

        return out;
    }
  ",
      "uniforms": {}
    }
  ]
}
