attribute vec3 aPosition;
vec4 positionVec4 = vec4(aPosition, 1.0);
positionVec4.xy = positionVec4.xy * 2.0 - 1.0;
gl_Position = positionVec4;
uniform vec3 particles[${MAX_NUMBER}];
uniform vec3 colors[${MAX_NUMBER}];
vec2 st = gl_FragCoord.xy / resolution.xy;
vec2 st_c = 1.0 - 2.0 * st;
st_c.y *= resolution.y/resolution.x;
float angle = a * 2.0 * 5.1415;
mat2 R = mat2(cos(angle), sin(angle), -sin(angle), cos(angle));
for(int i = 0; i < ${MAX_NUMBER}; i++){
vec3 particle = particles[i];
float m = particle.z * 0.8;
vec3 color = colors[i]/ 255.0;
col += color / distance(st_c, pos) * m * mult ;
vec3 contr = output_color * output_color;
output_color = mix(output_color, contr, slide);
gl_FragColor = vec4(output_color, 1.0);
let palette = ["#FFAD21", "#00DD96", "#A23251", "#C946FF", "#005CAA"];
shader = new p5.Shader(this.renderer, vertShader, fragShader);
buffer = createGraphics(w, w, WEBGL);
bufferB = createGraphics(w, w);
for (let i = 0; i < MAX_NUMBER; i++){
let p = [random(-0.2, 0.2), random(-0.2, 0.4), random(0.04, 0.3)];
let col = palette[int(random(0, 5))];
colors.push([red(col), green(col), blue(col)]);
if ((random(0.0, 1.0) < 0.01) & (abs(angle - target_angle) < 0.01)){
target_angle = random(0.0, 1.0);
angle += (target_angle - angle) * 0.001;
let data = prepareData(particles, colors);
shader.setUniform("a", angle);
shader.setUniform("slide", 0.9);
shader.setUniform("resolution", [w, w]);
shader.setUniform("particles", data.particles);
shader.setUniform("colors", data.colors);
bufferB.image(buffer, 0, 0, w, w);
image(bufferB, (width - w) * 0.5, (height - w) * 0.5, w, w);
for (let i = 0; i < particles.length; i++){
let sp = speed * (1.0 + 0.02 * particles[i][2]);
let p = [particles[i][0] * sp, particles[i][1] * sp, particles[i][2] * sp];
particles.forEach((p, i) => {
if (x > 1.0 | x < - 1.0 | y > 1.0 | y < -1.0){
if (x > 2.0 | x < - 2.0 | y > 2.0 | y < -2.0){
p[0] = random(-0.5, 0.3);
p[1] = random(-0.3, 0.3);
p[2] = random(0.01, 0.4);
let col = palette[int(random(0, 5))];
colors[i] = [red(col), green(col), blue(col)];
function prepareData(arr, arr2){
let data = {"particles": [], "colors" : []}
data["particles"].push(...p);
data["colors"].push(...arr2[i]);