PGraphics + noSmooth() + alpha = 绘图伪像

PGraphics + noSmooth() + alpha = drawing artifacts

注:我也在Processing论坛上问过这个问题here

我有这个示例代码:

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);
}

我希望这段代码在用户按下鼠标的任何地方显示一个点。相反,我只能看到几个矩形区域中的点:

如果我删除了对 pg.noSmooth() 的调用或者如果我删除了 pg.stroke() 调用中的 alpha 值,那么它工作正常:

如果我用 pg.ellipse()pg.rect() 替换 pg.point() 调用,那么它也可以正常工作。

似乎组合使用 PGraphicsnoSmooth() 函数、point() 函数和 alpha 值会导致此错误行为。我已经在 Processing 3.3 和 Processing 3.5.2 中尝试过,我在两者中看到了相同的行为。

我是不是遗漏了什么明显的东西?

一点点挖掘后发现 JAVA2D 渲染器绘制了一个 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 并且 Andres Colubri 不得不处理。

FWIW 这是一个 hacky 解决方法:使用更大的距离,它确实以透明方式呈现且没有锯齿:

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);
}

请注意,我已将 PGraphics 分辨率设置为小 20 倍,然后将其放大,以便更容易看到像素落在 PGraphics 上的位置。不过,我没有缩放 mouseX,mouseY 坐标,因此您需要在测试时在左上角的小预览中绘制。 0.75 的距离起到了作用:根据我的测试,任何小于 0.7499995 的东西都会再次开始出现故障。