drawPoints = regl({
vert: `
precision highp float;
attribute float index;
uniform float pointSize, n;
uniform sampler2D colorscale;
uniform vec2 res;
varying vec3 color;
const float pi = ${Math.PI};
void main () {
// Make up a position
const float phi = ${Math.PI * (3 - Math.sqrt(5))};
float r = sqrt(index / (n - 1.0)) * (length(res) / res.x) * 0.707;
float theta = index * phi * (r < 1e-8 ? 0.0 : 1.0);
gl_Position = vec4(0.9 * vec2(cos(theta), sin(theta) * res.x / res.y) * r * 1.57, 0, 1);
// Sample up a color (for efficiency, in the vert shader, then pass to the fragment shader)
color = texture2D(colorscale, vec2(fract(theta / pi), 0.5)).rgb;
gl_PointSize = pointSize;
}`,
frag: `
precision highp float;
uniform sampler2D sdf;
uniform float pointSize, borderWidth, aaWidth, opacity;
uniform vec3 borderColor;
varying vec3 color;
float linearstep(float edge0, float edge1, float x) {
return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
}
void main () {
// 0.5 corresponds to the shape, so compute an SDF relative to that value
float sdf = (texture2D(sdf, gl_PointCoord.xy).r - 0.5) * pointSize * 0.5;
float alpha = 0.0 + linearstep(-borderWidth * 2.0 - aaWidth, -borderWidth * 2.0 + aaWidth, sdf) * opacity;
vec3 col = borderWidth == 0.0
? color
: mix(borderColor, color, linearstep(-aaWidth, aaWidth, sdf));
if (alpha == 0.0) discard;
// Use pre-multiplied alpha to get the blending correct
gl_FragColor = vec4(vec3(col), 1) * alpha;
}`,
attributes: {
index: new Array(MAX_POINTS).fill(0).map((_, i) => i)
},
blend: {
enable: true,
func: {
srcRGB: 1,
srcAlpha: 1,
dstRGB: "one minus src alpha",
dstAlpha: "one minus src alpha"
}
},
depth: { enable: false },
uniforms: {
res: (ctx) => [ctx.viewportWidth, ctx.viewportHeight],
n: regl.prop("count"),
sdf: regl.prop("sdf"),
pointSize: (ctx, props) => ctx.pixelRatio * props.pointSize * 2.0,
borderWidth: (ctx, props) =>
ctx.pixelRatio *
Math.min(
props.borderWidth * 0.5,
(props.pointSize - (2.0 * props.aaWidth) / ctx.pixelRatio) * 0.25
),
colorscale: regl.prop("colorscale.texture"),
aaWidth: regl.prop("aaWidth"),
opacity: regl.prop("opacity"),
borderColor: (ctx, props) => {
const c = d3.rgb(props.borderColor);
return [c.r / 255, c.g / 255, c.b / 255];
}
},
primitive: "point",
count: regl.prop("count")
})