{
  "name": "Prism",
  "type": "static",
  "passes": [
    {
      "name": "prism",
      "inputs": [
        "default"
      ],
      "glsl": "precision highp float;

varying vec2 textureCoordinate;
varying vec2 sourceTextureCoordinate;

// default uniforms for all filters
uniform float time_sec;
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

// 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

// effect uniforms
uniform float prismCopies;
uniform float prismSpread;
uniform float prismRotate;
uniform float chroma;

const vec2 prismCenter = vec2(0.5);

vec3 sampleChroma(vec2 uv, vec2 offset){
  vec2 uvOffset = offset /  outputSize;
  return vec3 (sampleInput(uv - uvOffset).r,
              sampleInput(uv + uvOffset).g,
              sampleInput(uv - uvOffset).b);
}

void main() {

  vec2 uv = sourceTextureCoordinate;
  vec2 center = prismCenter;

  vec2 ratio = vec2(outputSize.x / outputSize.y, 1.0);

  vec3 accum = vec3(0.0);
  float total = 0.0;

  float stepA = 6.28318530718 / prismCopies;

  for (int i = 0; i < int(prismCopies); i++){

    float a = (prismRotate * time_sec) + stepA * float(i);
    vec2 dir = vec2(cos(a), sin(a));
   // dir = normalize(dir * ratio);

    vec2 offUV = dir * prismSpread * 0.5;

    float subRot = 0.02 * float(i);
    float ca = cos(subRot);
    float sa = sin(subRot);
    mat2 rot = mat2(ca, -sa, sa, ca);

    vec2 sampUV = rot * (uv - center) + center + offUV;

    float m = 1.0  - smoothstep(0.5,1.0, length((uv - (center - offUV)) * 2.0));

    // chroma scalesWithSize
    vec2 chromaOffset = dir * chroma * outputSize / 1080.0f;
    vec3 col = sampleChroma(sampUV, chromaOffset);

    accum += col * m;
    total += m;
  }

  vec3 centerCol = sampleInput(uv).rgb;
  float r = length((uv - center) * ratio);
  float centerMask = 1.0 - smoothstep(0.1, 0.3, r);

  vec3 outColor = accum / max(total, 1e-4);
 vec4 color = vec4(mix(outColor, centerCol, centerMask), 1.0);
  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;
  float prismCopies;
  float prismSpread;
  float prismRotate;
  float chroma;
 } Uniforms;
constant float2 prismCenter = float2(0.5);

float3 sampleChroma(float2 uv, float2 offset, DefaultInputs defaultInputs, constant Uniforms & uniforms){
  float2 uvOffset = offset /  uniforms.output_size;
  return float3 (sampleInput(defaultInputs, uv - uvOffset).r,
              sampleInput(defaultInputs, uv + uvOffset).g,
              sampleInput(defaultInputs, uv - uvOffset).b);
}

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

  float2 uv = in.sourceTextureCoordinate;
  float2 center = prismCenter;

  float2 ratio = float2(uniforms.output_size.x / uniforms.output_size.y, 1.0);

  float3 accum = float3(0.0);
  float total = 0.0;

  float stepA = 6.28318530718 / uniforms.prismCopies;

  for (int i = 0; i < int(uniforms.prismCopies); i++){

    float a = (uniforms.prismRotate * (1.0 - uniforms.time_sec)) + stepA * float(i);
    float2 dir = float2(cos(a), sin(a));
   // dir = normalize(dir * ratio);

    float2 offUV = dir * uniforms.prismSpread * 0.5;

    float subRot = 0.02 * float(i);
    float ca = cos(subRot);
    float sa = sin(subRot);
    float2x2 rot = float2x2(ca, -sa, sa, ca);

    float2 sampUV = rot * (uv - center) + center + offUV;

    float m = 1.0  - smoothstep(0.5,1.0, length((uv - (center - offUV)) * 2.0));

    // chroma scalesWithSize
    float2 chromaOffset = dir * uniforms.chroma * uniforms.output_size / 1080.0f;
    float3 col = sampleChroma(sampUV, chromaOffset, defaultInputs, uniforms);

    accum += col * m;
    total += m;
  }

  float3 centerCol = sampleInput(defaultInputs, uv).rgb;
  float r = length((uv - center) * ratio);
  float centerMask = 1.0 - smoothstep(0.1, 0.3, r);

  float3 outColor = accum / max(total, 1e-4);
 float4 color = float4(mix(outColor, centerCol, centerMask), 1.0);
  return {toOutputFormat(color)};
}
      ",
      "uniforms": {
        "prismCopies": {
          "value": 5.0
        },
        "prismSpread": {
          "value": 0.6
        },
        "prismRotate": {
          "value": 0.25
        },
        "chroma": {
          "value": 4.0
        }
      }
    }
  ]
}
