precision lowp float;
#define numOfPoints 100
#define seed (653165)
#define a (1103515245)
#define c (12345)
#define m (1<<31)
#define PointDist 0.3
#define Thickness 0.003
#define RandomPoints 1000

vec2 posCache[numOfPoints];
vec2 points[numOfPoints];
vec3 colors[numOfPoints];

float rand(int i) {
    uint ui = uint(i);
    uint ua = uint(a);
    uint uc = uint(c);
    uint useed = uint(seed);
    ui += ua + useed;
    float v = float(ua * ui + uc + useed + useed);
    if (v == 0.) v = 1.;
    return abs(float(ui) / v);
}


float rand(float i) {
    float k = i;
    if (i == 0.) k = 1.;
    int i2 = int(i * 10000.0 + 500. / k);
    return (rand(int(i)) + rand(i2)) / 2.0;
}

vec3 hash23(vec2 src) {
    vec3 randV = vec3(rand(src.x), rand(src.y), rand(src.x * src.y + src.x + src.y + 8912.2793));
    randV += dot(randV, randV+vec3(3799.6274,9567.3518,8575.2724));

    return fract(randV);
}
vec2 hash32(vec3 src) {
    vec2 randV = vec2(rand(src.x), rand(src.y)) + vec2(rand(src.z), rand(src.z + 9463.9522));
    randV += dot(randV, randV+vec2(8183.0119,4912.9833));

    return fract(randV);
}
vec2 pointPos(int pointId, float t) {
    vec2 pos = posCache[pointId];
    vec2 aceleration = hash32(vec3(pos, float(seed)));
    vec2 A = vec2(
        abs(mod(t * aceleration.x + pos.x, 2.0) - 1.0),
        abs(mod(t * aceleration.y + pos.y, 2.0) - 1.0)
    );
    return A;
}

float dist2segment(vec2 p1, vec2 p2, vec2 p) {
    vec2 ab = p2 - p1;
    vec2 ap = p - p1;

    float t = dot(ap, ab) / dot(ab, ab);

    t = clamp(t, 0.0, 1.0);

    vec2 closestPoint = p1 + t * ab;

    return length(p - closestPoint);
}

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec2 uv = (fragCoord - iResolution.xy * 0.5) / iResolution.y;
    float time = iTime * 0.2;
    vec3 col = vec3(0);
    vec3 mixColor;
    float dist, lineDist, t, dist2Pixel;
    for (int i = numOfPoints - 1; i >= 0; --i) {
        posCache[i] = vec2(rand(float(i) + 6939.9375 + float(i) / 9.0 + 5.0), rand(float(i) + 539.2171 + float(i) / 5.0 + 9.0));
        points[i] = (pointPos(i, time) - 0.5) * iResolution.xy / iResolution.y;
        colors[i] = hash23(posCache[i]);
        dist2Pixel = distance(points[i], uv);
        if(dist2Pixel > PointDist) continue;

        for (int j = i + 1; j < numOfPoints; ++j) {
            dist = distance(points[i], points[j]);
            if (dist > PointDist) continue;
            lineDist = dist2segment(points[i], points[j], uv);
            if (lineDist >= Thickness) continue;

            vec2 ab = points[j] - points[i];
            vec2 ap = uv - points[i];
            t = dot(ap, ab) / dot(ab, ab);
            mixColor = mix(colors[i], colors[j], clamp(t, 0.0, 1.0));
            col += mixColor * (PointDist - dist) * 2.0;
        }
    }

    fragColor = vec4(col, 1.0);
}
