To start with a sidenote, in your code example you are not using textLayer.clear();
on the initial textLayer (this is relevant because PGraphics don't start out transparent). More importantly, I have found the real problem and the solution.
To pinpoint it I made a test sketch that more clearly separated the 4 different stages/options, which were present in your sketch already. I have added the test sketch below. I am using white-on-white so only the incorrect pixels will light up (which are none under option 1 direct drawing, so it starts all white). Press the mouse to cycle through the 4 options and see the result (the name of the option is displayed in the window title).
The problem is the interpolation of semi-transparent pixels on a transparent PGraphics. These pixels interpolate to the fully transparent background color. Suppose you draw a text (or any shape) on the transparent PGraphics. For anti-aliasing purposes it will have some semi-transparent pixels. When the background color is fully transparent black, the pixels will interpolate to transparent black. When the background color is fully transparent white, the pixels will interpolate to transparent white. If you then display the transparant PGraphics on a background with non-matching opaque color, the semi-transparent pixels will stand out. The default transparent background color used with clear() is black, so it will only look good on black/dark backgrounds.
The solution is to match the color of the transparent background used to clear a PGraphics with the color of the background it will eventually be displayed upon. To test this change the used background color in the test sketch below to white (which is in line with the actual background color) and you will see all artifacts in the semi-transparent pixels disappear.
At least this is my theory.
Test Code
To pinpoint it I made a test sketch that more clearly separated the 4 different stages/options, which were present in your sketch already. I have added the test sketch below. I am using white-on-white so only the incorrect pixels will light up (which are none under option 1 direct drawing, so it starts all white). Press the mouse to cycle through the 4 options and see the result (the name of the option is displayed in the window title).
The problem is the interpolation of semi-transparent pixels on a transparent PGraphics. These pixels interpolate to the fully transparent background color. Suppose you draw a text (or any shape) on the transparent PGraphics. For anti-aliasing purposes it will have some semi-transparent pixels. When the background color is fully transparent black, the pixels will interpolate to transparent black. When the background color is fully transparent white, the pixels will interpolate to transparent white. If you then display the transparant PGraphics on a background with non-matching opaque color, the semi-transparent pixels will stand out. The default transparent background color used with clear() is black, so it will only look good on black/dark backgrounds.
The solution is to match the color of the transparent background used to clear a PGraphics with the color of the background it will eventually be displayed upon. To test this change the used background color in the test sketch below to white (which is in line with the actual background color) and you will see all artifacts in the semi-transparent pixels disappear.
At least this is my theory.
Test Code
- PGraphics textLayer, pg1, pg2;
- int option;
- color backgroundColor = color(0); // color(255); // the transparency is enforced below
- void setup() {
- size(800, 800, P3D);
- PFont font = createFont("Arial", 200, true);
- textFont(font);
- textAlign(CENTER, CENTER);
- textLayer = createGraphics(width, height, P3D);
- textLayer.beginDraw();
- textLayer.background(backgroundColor, 0);
- textLayer.noStroke();
- textLayer.fill(255);
- textLayer.textFont(font);
- textLayer.textAlign(CENTER, CENTER);
- textLayer.text("TEST", width/2, height/2);
- textLayer.endDraw();
- PShape shapeTest = createShape();
- shapeTest.beginShape();
- shapeTest.noStroke();
- shapeTest.noFill();
- shapeTest.textureMode(NORMAL);
- shapeTest.texture(textLayer);
- shapeTest.vertex(0, 0, 0, 0);
- shapeTest.vertex(width, 0, 1, 0);
- shapeTest.vertex(width, height, 1, 1);
- shapeTest.vertex(0, height, 0, 1);
- shapeTest.endShape(CLOSE);
- pg1 = createGraphics(width, height, P3D);
- pg1.beginDraw();
- pg1.background(backgroundColor, 0);
- pg1.image(textLayer, 0, 0);
- pg1.endDraw();
- pg2 = createGraphics(width, height, P3D);
- pg2.beginDraw();
- pg2.background(backgroundColor, 0);
- pg2.shape(shapeTest);
- pg2.endDraw();
- }
- void draw() {
- background(255);
- switch(option) {
- case 0:
- frame.setTitle("1. Direct drawing");
- fill(255);
- text("TEST", width/2, height/2);
- break;
- case 1:
- frame.setTitle("2. textLayer PGraphics");
- image(textLayer, 0, 0);
- break;
- case 2:
- frame.setTitle("3. PGraphics + textLayer PGraphics");
- image(pg1, 0, 0);
- break;
- case 3:
- frame.setTitle("4. PGraphics + PShape + textLayer PGraphics");
- image(pg2, 0, 0);
- break;
- }
- }
- void mousePressed() {
- option = ++option%4;
- }