I could make it by Worley noise
Worley noise is a noise function introduced by Steven Worley in 1996. In computer graphics it is used to create procedural textures,that is textures that are created automatically in arbitrary precision and don't have to be drawn by hand. Worley noise comes close to simulating textures of stone, water, or cell noise.
https://thebookofshaders.com/12/
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform float u_time;
// Permutation polynomial: (34x^2 + x) mod 289
vec4 permute(vec4 x) {
return mod((34.0 * x + 1.0) * x, 289.0);
}
vec3 permute(vec3 x) {
return mod((34.0 * x + 1.0) * x, 289.0);
}
// Cellular noise, returning F1 and F2 in a vec2.
// Speeded up by using 2x2x2 search window instead of 3x3x3,
// at the expense of some pattern artifacts.
// F2 is often wrong and has sharp discontinuities.
// If you need a good F2, use the slower 3x3x3 version.
vec2 cellular2x2x2(vec3 P) {
#define K 0.142857142857 // 1/7
#define Ko 0.428571428571 // 1/2-K/2
#define K2 0.020408163265306 // 1/(7*7)
#define Kz 0.166666666667 // 1/6
#define Kzo 0.416666666667 // 1/2-1/6*2
#define jitter 0.8 // smaller jitter gives less errors in F2
vec3 Pi = mod(floor(P), 289.0);
vec3 Pf = fract(P);
vec4 Pfx = Pf.x + vec4(0.0, -1.0, 0.0, -1.0);
vec4 Pfy = Pf.y + vec4(0.0, 0.0, -1.0, -1.0);
vec4 p = permute(Pi.x + vec4(0.0, 1.0, 0.0, 1.0));
p = permute(p + Pi.y + vec4(0.0, 0.0, 1.0, 1.0));
vec4 p1 = permute(p + Pi.z); // z+0
vec4 p2 = permute(p + Pi.z + vec4(1.0)); // z+1
vec4 ox1 = fract(p1*K) - Ko;
vec4 oy1 = mod(floor(p1*K), 7.0)*K - Ko;
vec4 oz1 = floor(p1*K2)*Kz - Kzo; // p1 < 289 guaranteed
vec4 ox2 = fract(p2*K) - Ko;
vec4 oy2 = mod(floor(p2*K), 7.0)*K - Ko;
vec4 oz2 = floor(p2*K2)*Kz - Kzo;
vec4 dx1 = Pfx + jitter*ox1;
vec4 dy1 = Pfy + jitter*oy1;
vec4 dz1 = Pf.z + jitter*oz1;
vec4 dx2 = Pfx + jitter*ox2;
vec4 dy2 = Pfy + jitter*oy2;
vec4 dz2 = Pf.z - 1.0 + jitter*oz2;
vec4 d1 = dx1 * dx1 + dy1 * dy1 + dz1 * dz1; // z+0
vec4 d2 = dx2 * dx2 + dy2 * dy2 + dz2 * dz2; // z+1
// Sort out the two smallest distances (F1, F2)
#if 0
// Cheat and sort out only F1
d1 = min(d1, d2);
d1.xy = min(d1.xy, d1.wz);
d1.x = min(d1.x, d1.y);
return sqrt(d1.xx);
#else
// Do it right and sort out both F1 and F2
vec4 d = min(d1,d2); // F1 is now in d
d2 = max(d1,d2); // Make sure we keep all candidates for F2
d.xy = (d.x < d.y) ? d.xy : d.yx; // Swap smallest to d.x
d.xz = (d.x < d.z) ? d.xz : d.zx;
d.xw = (d.x < d.w) ? d.xw : d.wx; // F1 is now in d.x
d.yzw = min(d.yzw, d2.yzw); // F2 now not in d2.yzw
d.y = min(d.y, d.z); // nor in d.z
d.y = min(d.y, d.w); // nor in d.w
d.y = min(d.y, d2.x); // F2 is now in d.y
return sqrt(d.xy); // F1 and F2
#endif
}
void mainImage( out vec4 fragColor, in vec2 fragCoord ){
vec2 uv = (fragCoord.xy - iResolution.xy*.5)/iResolution.y;
float w = 1. - dot(uv, uv)*3.;
uv *= 48.;
vec2 ip = floor(uv);
vec2 v = cellular2x2x2(vec3(uv, iTime/2.));
float c = v.x; //v.y - v.x
c -= .35*w;
c = smoothstep(0., max(.1/c, 0.), c);
vec3 col = mix(vec3(0), vec3(1), c);
fragColor = vec4(sqrt(max(col, 0.)), 1);
}
you can see this In shadertoy https://www.shadertoy.com/view/XlSBDz
GL_POINTS
on screen quad. These would have variable size of point as function of distance from screen center and would be textured as circle. Their screen position would be precomputed using Hammersley Point Set – mdkdy Jan 05 '18 at 20:22