What's the right approach to draw in / overlay PGraphics with transparency?

Hi! What would be the right way to have multiple PGraphics with transparency and draw them on top of each other to avoid tinting?

I’ll try to show the issue with some images and code:



PGraphics pg;
int mode = 0;
void setup() {  
  size(600, 600, P2D);
}

void draw() {
}
void keyPressed() {
  if (key == ' ') {    
    // draw random stuff on the background
    randomSeed(0);
    background(255, 40, 20);
    for (int i=0; i<50; i++) {
      pushMatrix();
      translate(random(width), random(height));
      rotate(i);
      rectMode(CENTER);
      noStroke();
      fill(random(50), random(100), random(255));
      rect(0, 0, 200, 50, 10);
      popMatrix();
    }

    // capture the background image for mode 2
    PImage bg = get();

    // create the top layer
    pg = createGraphics(width, height, P2D);
    pg.beginDraw();

    // The core of the issue: how to clear the layer?
    if(mode == 0) {
      pg.clear();
    } else if(mode == 1) {
      pg.background(255, 40, 20, 0);
    } else {
      pg.background(bg);
    }

    // draw white transparent lines
    pg.strokeWeight(5);
    pg.stroke(255, 40);
    for (int i=0; i<200; i++) {
      pg.line(i*3, 0, width-i*3, height);
    }
    pg.endDraw();

    // draw the layer to the main canvas
    image(pg, 0, 0);

    save("mode" + mode + ".png");
    mode = ++mode % 3;
  }
}

In that program I create some random graphics as a background and a layer with transparency to place on top. In the real program there are many such layers.

If one uses clear() to clear the PGraphics, I believe it’s setting every pixel to the color (0, 0, 0, 0) which is transparent black. If we draw transparent objects on such a layer, the transparent areas are tinted gray, as you can see the darkening of the red background, even if I’m drawing transparent white lines.

A second option would be to avoid clear() and use background() instead. In the second image you can see the result of calling backrgound with the red background color and 0 as alpha value. It no longer tints gray, but now everything is tinted red instead.

I assume the way to avoid any tint would be closer to the third approach: use the existing background image to clear the PGraphics, while setting the alpha to 0 (I didn’t do that in this program). I assume the way to do that would be to iterate over all pixels in the PGraphics and set the alpha value to 0. I don’t think any of the Processing functions allows to set just one channel (for instance, the alpha channel to 0). By doing this the transparent objects are not tinted to gray or red, but are only a combination of the drawing color and the background.

Can you suggest any references for learning about transparency and blending?
Is there a different technique you would use in this situation? (a blendMode, a shader…)

1 Like

I think I found out what is going on. Apparently this did not happen in Processing 2.

1 Like

Try converting it into a PraxisLIVE node (or I can) and test there. Premultiplied alpha is used throughout in the extended P2D/P3D renderer there, so you’ll know whether this fixes it.

Yesterday I started watching your presentation of PraxisLive in Poland :slight_smile:

1 Like

The day before I was giving the same presentation in Bristol! :smile: