precision highp float;
uniform sampler2D u_image;
uniform float u_scale;
uniform vec2 u_texSize;
varying vec2 v_texCoord;



float c_x0 = -1.0;
float c_x1 =  0.0;
float c_x2 =  1.0;
float c_x3 =  2.0;




vec4 CubicLagrange(vec4 A, vec4 B, vec4 C, vec4 D, float t) {
  return A *
    ((t - c_x1) / (c_x0 - c_x1) *
    (t - c_x2) / (c_x0 - c_x2) *
    (t - c_x3) / (c_x0 - c_x3)) +
    B *
    ((t - c_x0) / (c_x1 - c_x0) *
    (t - c_x2) / (c_x1 - c_x2) *
    (t - c_x3) / (c_x1 - c_x3)) +
    C *
    ((t - c_x0) / (c_x2 - c_x0) *
    (t - c_x1) / (c_x2 - c_x1) *
    (t - c_x3) / (c_x2 - c_x3)) +
    D *
    ((t - c_x0) / (c_x3 - c_x0) *
    (t - c_x1) / (c_x3 - c_x1) *
    (t - c_x2) / (c_x3 - c_x2));
}

vec4 BicubicLagrange(sampler2D image, vec2 texCoord, vec2 pixelSize) {

  vec2 textureSize = 1. / pixelSize;
  vec2 f = fract(texCoord * textureSize + .5);
  vec2 uv = (floor(texCoord * textureSize - .5) + .5) / textureSize;

  vec4 C00 = texture2D(image, uv + vec2(-pixelSize.x, -pixelSize.y));
  vec4 C10 = texture2D(image, uv + vec2(0.0, -pixelSize.y));
  vec4 C20 = texture2D(image, uv + vec2(pixelSize.x, -pixelSize.y));
  vec4 C30 = texture2D(image, uv + vec2(2.0 * pixelSize.x, -pixelSize.y));

  vec4 C01 = texture2D(image, uv + vec2(-pixelSize.x, 0.0));
  vec4 C11 = texture2D(image, uv + vec2(0.0, 0.0));
  vec4 C21 = texture2D(image, uv + vec2(pixelSize.x, 0.0));
  vec4 C31 = texture2D(image, uv + vec2(2.0 * pixelSize.x, 0.0));

  vec4 C02 = texture2D(image, uv + vec2(-pixelSize.x, pixelSize.y));
  vec4 C12 = texture2D(image, uv + vec2(0.0, pixelSize.y));
  vec4 C22 = texture2D(image, uv + vec2(pixelSize.x, pixelSize.y));
  vec4 C32 = texture2D(image, uv + vec2(2.0 * pixelSize.x, pixelSize.y));

  vec4 C03 = texture2D(image, uv + vec2(-pixelSize.x, 2.0 * pixelSize.y));
  vec4 C13 = texture2D(image, uv + vec2(0.0, 2.0 * pixelSize.y));
  vec4 C23 = texture2D(image, uv + vec2(pixelSize.x, 2.0 * pixelSize.y));
  vec4 C33 = texture2D(image, uv + vec2(2.0 * pixelSize.x, 2.0 * pixelSize.y));

  vec4 CP0X = CubicLagrange(C00, C10, C20, C30, f.x);
  vec4 CP1X = CubicLagrange(C01, C11, C21, C31, f.x);
  vec4 CP2X = CubicLagrange(C02, C12, C22, C32, f.x);
  vec4 CP3X = CubicLagrange(C03, C13, C23, C33, f.x);

  return CubicLagrange(CP0X, CP1X, CP2X, CP3X, f.y);

}

void main() {
  gl_FragColor = BicubicLagrange(u_image, v_texCoord, u_texSize);
}
