{
  "name": "Swipe up (Vertical swipe)",
  "curve": "Cubic Out",
  "type": "fixed-intro",
  "duration": 1.5,
  "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 textureCoordinate [[user(locn0)]]; 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 input_size;
  float2 output_size;
  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, 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 = 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, uniforms);
  float4 color = base;
  return {toOutputFormat(color)};
}
  ",
      "uniforms": {}
    }
  ]
}
