Shader.AA_CIRCLE ??= Shader(`void main(){ float l = .5-length(uv-.5); float op = clamp(l/fwidth(l)+.5, 0., 1.); color = arg0()*op; }`, COLOR) const circles = new Float32Array(20).fill(NaN) render = () => { ctx.reset(pixelRatio/ctx.width, 0, 0, pixelRatio/ctx.height, .5, .5) let {x, y} = ctx.from(cursor) ctx.shader = Shader.AA_CIRCLE let r = 50 ctx.drawRect(x-r, y-r, r*2, r*2, vec4(.5)) for(let i = 0; i < circles.length; i += 2){ const r2 = r+(r*=.9) let px = circles[i] - x, py = circles[i+1] - y const d = r2/hypot(px, py) if(!d) px = 0, py = r2 // catch NaN else px *= d, py *= d circles[i] = x += px circles[i+1] = y += py ctx.drawRect(x-r, y-r, r*2, r*2, vec4(r*.01)) } }