{
  "name": "Swipe up (Vertical swipe)",
  "curve": "Cubic Out",
  "type": "fixed-intro",
  "duration": 1.5,
  "passes": [
    {
      "name": "vertical swipe",
      "inputs": [
        "default"
      ],
      "glsl": "
               varying vec2 sourceTextureCoordinate;

               uniform vec2 outputSize;
               uniform float progress;

               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 = progress;
                 float yPx = getY(p);

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

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

                 vec4 color = motionBlur(uv, blurCurve);
                 gl_FragColor = toOutputFormat(color);
               }
",
      "metal": "using namespace metal;
struct fragmentIn { float2 textureCoordinate [[user(locn0)]]; float2 sourceTextureCoordinate [[user(locn1)]]; };
struct fragmentOut { float4 _gl_FragColor [[color(0)]]; };
typedef struct {
  float4x4 content_transform;
  float4x4 texture_transform;
  float progress;
  float2 output_size;
 } 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, constant Uniforms & uniforms){
  float offset = (10.0 / uniforms.output_size.y) * 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) {

  float2 uv = in.sourceTextureCoordinate;

  float p = uniforms.progress;
  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;

  float4 color = motionBlur(uv, blurCurve, defaultInputs, uniforms);
  return {toOutputFormat(color)};
}
",
      "uniforms": {}
    }
  ]
}
