2

Note: I also asked this question on the Processing forum here.

I have this sample code:

PGraphics pg;

void setup() {
  size(400, 500);
  pg = createGraphics(width, height);

  pg.noSmooth();
  pg.beginDraw();
  pg.background(0, 0, 255);
  pg.endDraw();
}

void draw() {

  if (mousePressed) {
    pg.beginDraw();
    pg.stroke(255, 254);
    pg.point(mouseX, mouseY);
    pg.endDraw();
  }

  image(pg, 0, 0, width, height);
}

I would expect this code to show a point wherever the user presses the mouse. Instead, I am only able to see points in a couple rectangular areas:

buggy window

If I remove the call to pg.noSmooth() or if I remove the alpha value in the pg.stroke() call, then it works fine:

working window

If I replace the pg.point() call with pg.ellipse() or pg.rect() then it also works fine.

It seems like the combination of using a PGraphics, the noSmooth() function, the point() function, and an alpha value results in this buggy behavior. I’ve tried in Processing 3.3 and Processing 3.5.2 and I see the same behavior in both.

Am I missing something obvious?

Kevin Workman
  • 41,537
  • 9
  • 68
  • 107
  • it does indeed look like noSmooth() is causing the issue. FAIK, for PGraphics you should call it within `beginDraw()` `endDraw()` calls. Might be a bug with the Java2D renderer – George Profenza Jan 28 '19 at 18:43
  • @GeorgeProfenza Hey George! Interestingly, if I move the call to `pg.noSmooth()` to be after the call to `pg.beginDraw()`, then I get a warning saying `smooth() can only be used before beginDraw()` and the call is ignored (everything is still antialiased). – Kevin Workman Jan 28 '19 at 18:46
  • Hey Kevin :) Regarding `pg.noSmooth()` you're right, my bad, got it the other way around. that's weird bug I gotta say. – George Profenza Jan 28 '19 at 18:55
  • @GeorgeProfenza Yeah, the [docs](https://processing.org/reference/createGraphics_.html) agree with your first statement, that `smooth()` / `noSmooth()` should be called between `beginDraw()` and `endDraw()`. That might be a separate issue of docs being out of date? – Kevin Workman Jan 28 '19 at 19:09
  • FWIW, the issue doesn't occur on the `P2D` renderer (`((PGraphicsOpenGL) g).textureSampling(2);` and as far as I can tell the `FX2D` renderer [doesn't have smooth](https://github.com/processing/processing/blob/master/core/src/processing/javafx/PGraphicsFX2D.java#L996) ? It seems to be an issue with the Java2D renderer alone – George Profenza Jan 28 '19 at 20:11
  • @GeorgeProfenza Weirdly enough, if I switch to the `P2D` renderer (by passing `P2D` into the `size()` and `createGraphics()` functions), then I don't see the dots at all. Also, the `set()` function seems to work okay. I filed a bug on GitHub [here](https://github.com/processing/processing/issues/5777). – Kevin Workman Jan 28 '19 at 22:47

1 Answers1

3

After a wee bit of digging up turns out the JAVA2D renderer draws a point as a diagonal line(line(x, y, x + EPSILON, y + EPSILON);) with a very very very small spacing (static final float EPSILON = 0.0001f;). My guess is this particular configuration the lack aliasing might mean both points of this diagonal line land on the same pixel and end up not being rendered on the top right area which. Why that area and how come this small distance I don't know, but it sounds a bit like the headaches Jakub Valtar and Andres Colubri had to deal with.

FWIW here's a hacky workaround: using a larger distance that does get rendered with transparency and no aliasing:

PGraphics pg;

void setup() {
  size(400, 500);
  noSmooth();

  pg = createGraphics(width/20, height/20);
  pg.beginDraw();
  // just for debug purposes: rectangle with edge
  pg.fill(0, 0, 255);
  pg.rect(0,0,pg.width-1,pg.height-1);
  pg.stroke(255,255,255, 128);
  pg.endDraw();

}

void pointNoSmooth(PGraphics pg, float x,float y){
  pg.beginShape();
  pg.vertex(x,y);
  pg.vertex(x + 0.75,y);//any less than 0.75 distance between vertices and there's nothing to render with aliasing
  pg.endShape();
}

void draw() {
  background(255);
  if (mousePressed) {
    pg.beginDraw();
    pointNoSmooth(pg,mouseX,mouseY);
    pg.endDraw();
  }
  // render upscaled
  image(pg, 0, 0, width, height);
  // render small preview in TL corner
  image(pg,0,0);
}

Notice that I've set the PGraphics resolution 20 times smaller, then drawn it upscaled so it's easier to see where the pixels land on the PGraphics. I'm not scaling the mouseX,mouseY coordinates though, so you'll need to draw in the small top left preview when testing. That 0.75 distance does the trick: from what I've tested, anything smaller than 0.7499995 starts acting buggy again.

George Profenza
  • 50,687
  • 19
  • 144
  • 218
  • 1
    This is a great answer, thanks for doing the research! This does indeed seem to be the case- it becomes even more obvious if we use a nested for loop to fill the `PGraphics` with dots. Interestingly, if I remove the alpha argument, I no longer see points at all, even with an epsilon of .75. I'm going to add this info to [the bug](https://github.com/processing/processing/issues/5777). Thanks again George! – Kevin Workman Jan 29 '19 at 17:55