Very weird stuff going on with colors and transparency with the P2D renderer

PGraphics pg;

void setup() {
  size(800, 800, P2D);

  pg = createGraphics(width, height, P2D);

  pg.beginDraw();

  pg.noStroke();

  pg.clear();

  pg.fill(255, 127);
  pg.rect(0, 0, 195, height);
  printColor(pg.get(10, 10));

  pg.endDraw();

  background(0);
  image(pg, 0, 0);
}

void draw() {
  pg.beginDraw();
  //pg.clear();

  pg.fill(255, 127);
  switch(frameCount) {
  case 1 :
    pg.rect(200, 0, 195, height);
    printColor(pg.get(210, 10));
    break;
  case 2 :
    pg.rect(400, 0, 195, height);
    printColor(pg.get(410, 10));
    break;
  case 3 :
    pg.rect(600, 0, 195, height);
    printColor(pg.get(610, 10));
    break;
  }

  pg.endDraw();

  background(0);
  image(pg, 0, 0);
}

void printColor(int c) {
  println("color RBGA: (" +
    red(c) + ", " +
    green(c) + ", " +
    blue(c) + ", " +
    alpha(c) + ")");
}

This is my attempt to figure out why my images are darker than they’re supposed to be sometimes, and I admit that I’m completely lost. It’s seriously messing up a project I’m trying to work on. Colors below are in RGBA format.

The 4 rectangles are supposed to be 255, 255, 255, 127 as I’ve set in the fill() methods. In the above code, the colors of the four rectangles are apparently 127, 127, 127, 127. If you comment out pg.clear(); in setup(), then the color of the fist rectangle is 229, 229, 229, 127 for some reason. Uncommenting pg.clear(); in draw() doesn’t seem to make a difference (besides making it so you can’t see anything which is expected). When I analyze the colors using an image editor, then they’re 63, 63, 63 when they should be 127, 127, 127 because it’s drawn onto the primary PGraphics set to 0, 0, 0, 255. In any case, I can’t get the first rectangle to even show up on screen.

Furthermore, If I change just the primary to the default renderer, it crashes. (I think this is supposed to be unsurprising, but makes the next result confusing.) If I instead change just pg to the default renderer or I change both to the default renderer, then all the colors in all situations described above are correct. The first rectangle even shows up. Unfortunately I kind of need P2D because it’s way faster, and I’m doing something that requires a lot of computation.

I can’t make sense of any of this. All I want to do is draw a translucent shape onto a transparent PGraphics then draw that onto the primary without having all of these strange color anomalies.

I originally posted on the GitHub, but they directed me here. Am I just doing it wrong, or is this truly a bug?

Hi, been experimenting for about an hour and yeah, cant seem to make sense of it either, I changed the renderer to JAVA2D instead of P2D for both the pg layer and the main and it helped on my end, maybe try that? Its got me stumped that even the first rect isn’t showing, its done in setup but you’re not clearing the pg at all so it should stay, when things break in P2D or P3D I generally try other renderers

Thanks for trying.

Btw, when I say “default renderer”, I’m referring to JAVA2D. (Or at least I’m pretty sure that’s correct. It’s weirdly difficult to find a definitive answer on that.) My goal here is to find out if this is a bug that needs to be fixed, or if I’m just ignorant on whatever the correct way is to do what I’m trying to do. If we find that it’s a bug, then I’ll have to ask for my GitHub issue to be reopened. It would also be nice to find out exactly what’s wrong, but I can only endure so much headache at a time

P2D is just so much faster and actually looks a little better for my specific use case

Thats fair enough, did you actually use size(800,800,JAVA2D) or just size(800,800) ?
Im not sure if java2d is the default or not but I have found sometimes using it like that works when I have issues, best of luck

I just verified that JAVA2D is the default renderer with this line:

println("Renderer: " + g.getClass().getName());

I used size(800,800)

1 Like

Ok then, wasn’t sure about that either, sorry I couldn’t help then, must be an issue with P2D

Check out Add support for pre-multiplied alpha · Issue #3391 · processing/processing · GitHub

Processing doesn’t use premultiplied alpha, and unlike the Java2D back-end, the OpenGL back-end doesn’t (and can’t easily) correct for this.

This is one difference when using the Processing nodes in PraxisLIVE as it uses premultiplied alpha throughout, which leads to correct behaviour.

2 Likes

How willing are you to explain exactly what’s going on with my code and possibly how to fix it? This seems like quite a deep rabbit hole to plunge into alone.

Hello @PianoMastR64,

When using PGraphics I have always had a setup frame first; I may have encountered this issue in the past and in the habit of doing this now.
This will get around that first frame behavior.

This code has the PG setup frame and will toggle between PGraphics renderers (P2D and JAVA2D):

PGraphics pg;

boolean toggle;

void setup() 
  {
  size(800, 800, P2D);

  if (toggle)
    {
    pg = createGraphics(width, height, JAVA2D);
    println("PG P2D");
    println("Renderer: " + g.getClass().getName());
    println("Renderer: " + pg.getClass().getName());
    }
  else
    {
    pg = createGraphics(width, height, P2D);
    //println("PG JAVA2D");
    println("Renderer: " + g.getClass().getName());
    println("Renderer: " + pg.getClass().getName());
    }

  //Setup frame workaround
  pg.beginDraw();
  //pg.clear();
  pg.endDraw();

  pg.beginDraw();
  pg.noStroke();
  //pg.clear();
  pg.fill(255, 127);
  pg.rect(0, 0, 195, height);
  println(hex(pg.get(10, 10)));
  pg.endDraw();

  background(0);
  image(pg, 0, 0);
  }

void draw() 
  {
  pg.beginDraw();
  //pg.clear();

  pg.fill(255, 127);
  switch(frameCount) {
  case 1 :
    pg.rect(200, 0, 195, height);
    println(hex(pg.get(210, 10)));
    break;
  case 2 :
    pg.rect(400, 0, 195, height);
    println(hex(pg.get(410, 10)));
    break;
  case 3 :
    pg.rect(600, 0, 195, height);
    println(hex(pg.get(610, 10)));
    break;
    }

  pg.endDraw();

  background(0);
  image(pg, 0, 0);
  }

void keyPressed()
  {
  toggle = !toggle;
  frameCount = -1;  // See https://discourse.processing.org/t/about-restarting/22557/3
  }

That still leaves the color mixing issues/behavior mentioned previously.

Reference:
https://discourse.processing.org/t/about-restarting/22557/3

:)