[vert.glsl]

#version 120

attribute vec2 in_Position;

varying vec4 pass_Position;

void main(void)
{
    pass_Position = vec4(0.5 * in_Position + 0.5, 0.0, 1.0);
    gl_Position = vec4(in_Position, 0.5, 1.0);
}

[frag.glsl]

#version 120

uniform sampler2D u_Texture;

varying vec4 pass_Position;

float segdist(vec2 p1, vec2 p2, vec2 a)
{
    float d = max(1e-10, dot(p2 - p1, p2 - p1));
    float t = clamp(dot(a - p1, p2 - p1) / d, 0.0, 1.0);
    return distance(a, mix(p1, p2, t));
}

void main(void)
{
    float width = 800.0;
    float height = 600.0;
    float texture_width = 256.0;
    float line_width = 1.2;
    float dot_size = 1.0;
    vec4 delta = vec4(1.0 / texture_width, 0.0,
                      2.0 / texture_width, 0.0);

    vec2 p = pass_Position.xy;
    vec2 tc = vec2(floor(p.x * texture_width) / texture_width, p.y);
    float t = p.x * texture_width - floor(p.x * texture_width);
    vec4 c;
    c[0] = texture2D(u_Texture, tc - delta.xy).x;
    c[1] = texture2D(u_Texture, tc).x;
    c[2] = texture2D(u_Texture, tc + delta.xy).x;
    c[3] = texture2D(u_Texture, tc + delta.zw).x;

    /* Find the 4 closest points in screen space */
    vec2 p0 = vec2((tc.x - delta.x) * width, c[0] * height);
    vec2 p1 = vec2((tc.x          ) * width, c[1] * height);
    vec2 p2 = vec2((tc.x + delta.x) * width, c[2] * height);
    vec2 p3 = vec2((tc.x + delta.z) * width, c[3] * height);
    vec2 a = vec2(p.x * width, p.y * height);

    /* Compute distance to segments */
    float d =        segdist(p0, p1, a);
          d = min(d, segdist(p1, p2, a));
          d = min(d, segdist(p2, p3, a));

    /* Compute distance to dots */
    d = min(d, length(a - p0) - dot_size);
    d = min(d, length(a - p1) - dot_size);
    d = min(d, length(a - p2) - dot_size);
    d = min(d, length(a - p3) - dot_size);

    /* Add line width */
    float lum = clamp(line_width - d, 0.0, 1.0);

    /* Compensate for sRGB */
    lum = pow(1.0 - lum, 1.0 / 2.4);

    /* Choose some funny colours */
    gl_FragColor = vec4(mix(p.x, 1.0, lum), lum, lum, 1.0);
}

