PGraphics + noSmooth() + alpha = drawing artifacts

回眸只為那壹抹淺笑 提交于 2020-02-02 10:59:06

问题


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:

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

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?


回答1:


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.



来源:https://stackoverflow.com/questions/54408259/pgraphics-nosmooth-alpha-drawing-artifacts

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!