Hi.
I am translating a sketch from P5.java to P5.js. In java, it runs nice and smooth at a frameRate near 60. In p5.js the frameRate drops to around 4 f/s and a lot of details are missing.
How can I improve this, or is WEBGL really that bad?
Thanks.
Edit: Please skip to the actual sketch I am translating here below.
P5.java:
int num;
float pt[];
int style[];
float sin_ar[];
float cos_ar[];
float PRECISION = 1.0;
int AR_LENGTH = 360;
void setup() {
size(600, 600, P3D);
background(255);
smooth();
sin_ar = new float[AR_LENGTH];
cos_ar = new float[AR_LENGTH];
for (int i = 0; i < AR_LENGTH; i++) {
sin_ar[i]= sin(i*radians(PRECISION));
cos_ar[i]= cos(i*radians(PRECISION));
}
num = 150;
pt = new float[6*num]; // rotx, roty, deg, rad, w, speed
style = new int[2*num]; // color, render style
// Set up arc shapes
int index = 0;
float prob;
for (int i = 0; i < num; i++) {
pt[index++] = random(PI*2); // Random X axis rotation
pt[index++] = random(PI*2); // Random Y axis rotation
pt[index++] = random(60, 80); // Short to quarter-circle arcs
if (random(100)>90) pt[index]=(int)random(8, 27)*10;
pt[index++] = int(random(2, 50)*5); // Radius. Space them out nicely
pt[index++] = random(4, 32); // Width of band
if (random(100)>90) pt[index]=random(40, 60); // Width of band
pt[index++] = radians(random(5, 30))/2; // Speed of rotation
// get colors
prob = random(100);
if (prob < 30) style[i*2]=color_blend(random(1), 255, 0, 100, 255, 0, 0, 210);
else if (prob < 70) style[i*2]=color_blend(random(1), 0, 153, 255, 170, 225, 255, 210);
else if (prob < 90) style[i*2]=color_blend(random(1), 200, 255, 0, 150, 255, 0, 210);
else style[i*2]=color(255, 255, 255, 220);
if (prob < 50) style[i*2]=color_blend(random(1), 200, 255, 0, 50, 120, 0, 210);
else if (prob < 90) style[i*2]=color_blend(random(1), 255, 100, 0, 255, 255, 0, 210);
else style[i*2] = color(255, 255, 255, 220);
style[i*2+1]=(int)(random(100))%3;
}
}
void draw() {
background(0);
println(frameRate);
int index=0;
translate(width/2, height/2, 0);
rotateX(PI/6);
rotateY(PI/6);
for (int i=0; i<num; i++) {
pushMatrix();
rotateX(pt[index++]);
rotateY(pt[index++]);
if (style[i*2+1]==0) {
stroke(style[i*2]);
noFill();
strokeWeight(1);
arc_line(0, 0, pt[index++], pt[index++], pt[index++]);
} else if (style[i*2+1]==1) {
fill(style[i*2]);
noStroke();
arc_line_bars(0, 0, pt[index++], pt[index++], pt[index++]);
} else {
fill(style[i*2]);
noStroke();
arc_b(0, 0, pt[index++], pt[index++], pt[index++]);
}
// increase rotation
pt[index-5]+=pt[index]/10;
pt[index-4]+=pt[index++]/20;
popMatrix();
}
}
// Get blend of two colors
public int color_blend(float fract,
float r, float g, float b,
float r2, float g2, float b2, float a) {
r2 = (r2 - r);
g2 = (g2 - g);
b2 = (b2 - b);
return color(r + r2 * fract, g + g2 * fract, b + b2 * fract, a);
}
// Draw arc line
public void arc_line(float x, float y, float deg, float rad, float w) {
int a=(int)(min (deg/PRECISION, AR_LENGTH-1));
int numlines=(int)(w/2);
for (int j=0; j<numlines; j++) {
beginShape();
for (int i=0; i<a; i++) {
vertex(cos_ar[i]*rad+x, sin_ar[i]*rad+y);
}
endShape();
rad += 2;
}
}
// Draw arc line with bars
public void arc_line_bars(float x, float y, float deg, float rad, float w) {
int a = int((min (deg/PRECISION, AR_LENGTH-1)));
a /= 4;
beginShape(QUADS);
for (int i=0; i<a; i+=4) {
vertex(cos_ar[i]*(rad)+x, sin_ar[i]*(rad)+y);
vertex(cos_ar[i]*(rad+w)+x, sin_ar[i]*(rad+w)+y);
vertex(cos_ar[i+2]*(rad+w)+x, sin_ar[i+2]*(rad+w)+y);
vertex(cos_ar[i+2]*(rad)+x, sin_ar[i+2]*(rad)+y);
}
endShape();
}
// Draw solid arc
public void arc_b(float x, float y, float deg, float rad, float w) {
int a = int(min (deg/PRECISION, AR_LENGTH-1));
beginShape(QUAD_STRIP);
for (int i = 0; i < a; i++) {
vertex(cos_ar[i]*(rad)+x, sin_ar[i]*(rad)+y);
vertex(cos_ar[i]*(rad+w)+x, sin_ar[i]*(rad+w)+y);
}
endShape();
}
P5.js:
let num;
let pt = [];
let style = [];
let sin_ar = [];
let cos_ar = [];
const PRECISION = 1.0;
let AR_LENGTH = 360;
function setup() {
createCanvas(600, 600, WEBGL);
background(255);
for (let i = 0; i < AR_LENGTH; i++) {
sin_ar[i] = sin(i * radians(PRECISION));
cos_ar[i] = cos(i * radians(PRECISION));
}
num = 150;
// Set up arc shapes
let index = 0;
let prob;
for (let i = 0; i < num; i++) {
pt[index++] = random(PI * 2); // Random X axis rotation
pt[index++] = random(PI * 2); // Random Y axis rotation
pt[index++] = random(60, 80); // Short to quarter-circle arcs
if (random(100) > 90) pt[index] = random(8, 27) * 10;
pt[index++] = int(random(2, 50) * 5); // Radius. Space them out nicely
pt[index++] = random(4, 32); // Width of band
if (random(100) > 90) pt[index] = random(40, 60); // Width of band
pt[index++] = radians(random(5, 30)) ; // Speed of rotation
// get colors
prob = random(100);
if (prob < 30)
style[i * 2] = color_blend(random(1), 255, 0, 100, 255, 0, 0, 210);
else if (prob < 70)
style[i * 2] = color_blend(random(1), 0, 153, 255, 170, 225, 255, 210);
else if (prob < 90)
style[i * 2] = color_blend(random(1), 200, 255, 0, 150, 255, 0, 210);
else style[i * 2] = color(255, 255, 255, 220);
if (prob < 50)
style[i * 2] = color_blend(random(1), 200, 255, 0, 50, 120, 0, 210);
else if (prob < 90)
style[i * 2] = color_blend(random(1), 255, 100, 0, 255, 255, 0, 210);
else style[i * 2] = color(255, 255, 255, 220);
style[i * 2 + 1] = int(random(100)) % 3;
}
//ortho([left], [right], [bottom], [top], [near], [far])
//ortho(-width/2, width/2, -height/2, height/2, -height / 1, height / 2 );
}
function draw() {
background(0);
translate(-width/2, height/2);
let index = 0;
translate(width / 2, -height / 2, 0);
rotateX(PI / 6);
rotateY(PI / 6);
print(frameRate());
for (let i = 0; i < num; i++) {
push();
rotateX(pt[index++]);
rotateY(pt[index++]);
if (style[i * 2 + 1] == 0) {
stroke(style[i * 2]);
noFill();
strokeWeight(1.5);
arc_line(0, 0, pt[index++], pt[index++], pt[index++]);
} else if (style[i * 2 + 1] == 1) {
fill(style[i * 2]);
noStroke();
arc_line_bars(0, 0, pt[index++], pt[index++], pt[index++]);
} else {
fill(style[i * 2]);
noStroke();
arc_b(0, 0, pt[index++], pt[index++], pt[index++]);
}
// increase rotation
pt[index - 5] += pt[index] / 10;
pt[index - 4] += pt[index++] / 20;
pop();
}
}
// Get blend of two colors
function color_blend(frac, r, g, b, r2, g2, b2, a) {
r2 = r2 - r;
g2 = g2 - g;
b2 = b2 - b;
return color(r + r2 * frac, g + g2 * frac, b + b2 * frac, a);
}
// Draw arc line
function arc_line(x, y, deg, rad, w) {
let a = min(deg / PRECISION, AR_LENGTH - 1);
let numlines = w / 2;
for (let j = 0; j < numlines; j++) {
beginShape();
for (let i = 0; i < a; i++) {
vertex(cos_ar[i] * rad + x, sin_ar[i] * rad + y);
}
endShape();
rad += 2;
}
}
// Draw arc line with bars
function arc_line_bars(x, y, deg, rad, w) {
let a = int(min(deg / PRECISION, AR_LENGTH - 1));
a /= 4;
beginShape(QUADS);
for (let i = 0; i < a; i += 4) {
vertex(cos_ar[i] * rad + x, sin_ar[i] * rad + y);
vertex(cos_ar[i] * (rad + w) + x, sin_ar[i] * (rad + w) + y);
vertex(cos_ar[i + 2] * (rad + w) + x, sin_ar[i + 2] * (rad + w) + y);
vertex(cos_ar[i + 2] * rad + x, sin_ar[i + 2] * rad + y);
}
endShape();
}
// Draw solid arc
function arc_b(x, y, deg, rad, w) {
let a = int(min(deg / PRECISION, AR_LENGTH - 1));
beginShape(QUAD_STRIP);
for (let i = 0; i < a; i++) {
vertex(cos_ar[i] * rad + x, sin_ar[i] * rad + y);
vertex(cos_ar[i] * (rad + w) + x, sin_ar[i] * (rad + w) + y);
}
endShape();
}