uniform vec4 u_color_stops[8];
uniform float u_color_offsets[8];
uniform int u_num_color_stops;
uniform vec2 u_start_point;
uniform vec2 u_end_point;

vec4 fragCoord() {
  vec4 f = gl_FragCoord;
  f.x += u_viewport.x;
  f.y = (u_viewport.y + u_viewport.w) - f.y;
  return f;
}

void main() {
  vec2 startPoint = (u_modelview * vec4(u_start_point, 0, 1)).xy;
  vec2 endPoint   = (u_modelview * vec4(u_end_point,   0, 1)).xy;
  float maxDist   = length(endPoint - startPoint);

  // Position relative to startPoint
  vec2 pos = fragCoord().xy - startPoint;

  // Gradient direction
  vec2 gradient = endPoint - startPoint;
  float gradientLength = length(gradient);

  // Current pixel, projected onto the line between the start point and the end point
  // The projection will be relative to the start point!
  vec2 proj = (dot(gradient, pos) / (gradientLength * gradientLength)) * gradient;

  // Offset of the current pixel
  float offset = length(proj) / maxDist;

  vec4 color = u_color_stops[0];
  for (int i = 1; i < u_num_color_stops; i ++) {
    if (offset >= u_color_offsets[i - 1])  {
      float o = (offset - u_color_offsets[i - 1]) / (u_color_offsets[i] - u_color_offsets[i - 1]);
      color = mix(u_color_stops[i - 1], u_color_stops[i], clamp(o, 0.0, 1.0));
    }
  }

  /* Pre-multiply */
  color.rgb *= color.a;

  setOutputColor(color * u_alpha);
}
