Rect(x,y,1,1); VS. point(x,y);

Can you guys try this? (try changing the size() on your computers)

boolean rectOrPoint;

void setup() {
  size(600, 300);  //play with these: make those bigger if you've got a fast modern computer
  rectOrPoint = false;
  println(rectOrPoint ? "rect(x, y, 1, 1);" : "point(x, y);");
}

void draw() {
  for (int j=0; j<height; j++) {
    for (int i=0; i<width; i++) {
      if (rectOrPoint) {
        fill(random(255), random(255), random(255));
        noStroke();
        rect(i, j, 1, 1);
      } else {
        noFill();
        stroke(random(255), random(255), random(255));
        point(i, j);
      }
    }
  }
  surface.setTitle((rectOrPoint ? "rect(x, y, 1, 1);" : "point(x, y);")+" @ "+round(frameRate));
}

void keyPressed() {
  rectOrPoint = !rectOrPoint;
  println(rectOrPoint ? "rect(x, y, 1, 1);" : "point(x, y);");
}

Well, the rect() is almost tenfold faster than the point() (yeah, my computer is that slow but maybe there’s more to it than meets the eye)

I’m raising it as it’s against my expectations :slight_smile: what ever could be simplier than painting a pixel with a color? a single assignment instruction! I mean opposite to arranging a rectangular with two nested loops along its hight and width, even if the rectangular is 1×1 pixel wide and high? that confuses me :slight_smile:

Is this known? Is this an issue?

1 Like

It drops to 2 fps quite quickly on my laptop when I increase the size. Did you leave out pixels[i] on purpose and is it purely a battle between rect & points?

Hi, Tiemen, thanks for getting involved.
Yes, I meant a bare competition of point vs rect. What frame rate did you get with rect()?
Thank you for the other idea of updating pixels directly. That seems useful!

You’re welcome, always interesting to see experiments like these. When I swap to rect(), with a window size of 1000x1000, it slowly drops to 5-4 fps and after ~10 seconds it’s stuck around 3

Have you considered replacing rect() with a PShape? :smile:

Nope, I was wondering about a fastest way to paint the whole sketch screen pixel by pixel :slight_smile:
So far I found out experimentally that a rect() of 1×1 pixel is way too faster than point(). the way you suggested, updating pixels as if of an image, seems prominsing :slight_smile:

In your sketch you using the default JAVA2D mode which means that most of Processing drawing commands like rect, ellipse etc use the underlying Java AWT to render the shape which is fast.

When you use point you are not using Java AWT in the same way, Processing is performing a three step process

  1. Load ALL the pixel data into an int array
  2. Change the array element corresponding to [x,y]
  3. Update the pixel data so that changes will appear on the screen

Although step (2) is fast the others are very slow by comparison.

3 Likes

PGraphics2D::point() actually calls PGraphics2D::line():

Which then calls PGraphics2D::strokeShape():

Which relies on field g2 of datatype Graphics2D to render it:

Which btW, belongs to package java.awt:
Docs.Oracle.com/en/java/javase/11/docs/api/java.desktop/java/awt/Graphics2D.html

2 Likes

Really interesting, thanks!

It sounds like your concept of “point” is somewhere between pixels[i]=c and calling set(x,y,c);.

But that isn’t what point() is in Processing. A point is a graphical marker for a geometric object, like a box() or sphere() or line(). In geometry a point is conceptually no-size (so invisible?), but the marker can’t be invisible–so should it be square or round? Should we be able to tell if points are closer or further away, or rotated or scaled?

For example, what do you expect this sketch to do?

point(10,10);
scale(2,2);
point(10,10);
scale(2,2);
point(10,10);
scale(2,2);
point(10,10);

…or, if you are drawing points in 3D space, what do you expect points to do under scale, rotation, or translation?

void setup() {
  size(400, 400, P3D);
  noLoop();
}
void draw() {
  background(128);
  translate(width/2, height/2);
  for (int i=0; i<256; i++) {
    stroke(i);
    rotateZ(0.13);
    scale(1.02);
    if (i%4==0) {
      point(1, 1, -0.2);
    }
  }
}

If you don’t want any of that – you want to flip pixels – then don’t use point! Use pixels[].

4 Likes

I guess you are right. I used to think of a point as an equivalent to a pixel. Or a voxel in 3D. I’ll have to reconsider

Some of this is specific to the renderer in size() – so really, you aren’t getting the “Processing” idea of a point so much as the JAVA2D or OpenGL idea of a point. In the default 2D, if you rotate by 45 degrees and then start drawing points none of your integer point coordinates are aligned with the pixel grid anymore. Grid alignment can cause some counterintuitive anti-aliasing artifacts – when a point isn’t grid-aligned, scaling and smoothing can sometimes change a single point() into two pixels, or four or five antialiased pixels, even in 2D. In OpenGL 3D, ideal points are circle-spheres – not voxels – which also works around the fact that free rotation could do strange things to a group of boxes with different orientations.

2 Likes

Addendum: there is a related discussion of (not) making point() consistent across renderers in this github issue: