{
  "name": "Super Wobble",
  "duration": 3,
  "curve": "Linear None",
  "passes": [
    {
      "name": "Super Wobble",
      "inputs": [
        "default"
      ],
      "glsl": "precision highp float;

varying vec2 textureCoordinate;
varying vec2 sourceTextureCoordinate;

// default uniforms for all filters
uniform float time;
uniform float strength;
uniform vec2 outputSize; // size of the output fbo
uniform vec2 inputSize; // size of the original default input texture
uniform vec2 tex0Size; // size of tex0 for this pass

uniform float maxZoom;

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

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

const float PI  = 3.14159265359;

vec2 rotate(vec2 p, float a){
  float s = sin(a);
  float c = cos(a);
  return vec2(c * p.x - s * p.y, s * p.x + c * p.y);
}

float easeOutExpo(float t){
  return (t >= 1.0) ? 1.0 : 1.0 - pow(2.0, -10.0 * t);
}

// effect uniforms
void main() {

  vec2 uv = sourceTextureCoordinate;
  vec2 ratio = outputSize.xy / outputSize.y;
  vec2 center = vec2(0.5,0.5);

  const float zoomInEnd = 0.1257;
  const float rotStart = 0.06285;
  const float rotEnd = 0.354;
  const float zoomOutEnd = 0.457;
  float scale;
  float angle = 0.0;

  if (progress < zoomInEnd){
    float t = smoothstep(0.0,1.0, progress / zoomInEnd);
    scale = mix(1.0, maxZoom, t);
  } else if (progress < rotEnd) {
    scale = maxZoom;
  } else if (progress < zoomOutEnd){
    float t = smoothstep(0.0,1.0, (progress - rotEnd) / (zoomOutEnd - rotEnd));
    scale = mix(maxZoom, 1.0, easeOutExpo(t));
  }else {
    scale = 1.0;
  }

  if (progress > rotStart && progress < rotEnd){
    float t = (progress - rotStart) / (rotEnd - rotStart);
    float osc = sin(t * PI * 12.0);
    angle = radians(30.0) * osc;
  }

  uv = uv - center;
  uv *= ratio;
  uv = rotate(uv, angle);
  uv /= ratio;
  uv = uv / scale + center;

  vec4 color = sampleInput(uv);
  gl_FragColor = toOutputFormat(color);
}
",
      "uniforms": {
        "maxZoom": {
          "value": 2
        }
      }
    }
  ]
}
