Text inaccuracies in P2D/P3D mode

I have been working on a project that involves a lot of text handling, and I’ve recently started trying to add some 3D rotations and transformations to some of the graphics. However, when I switch to the P3D renderer, the text comes out distorted and ugly.

Here is the default software renderer:

Here I’ve used the P3D renderer to transform the grid in 3D, and it also changes the look of the text pretty dramatically:

(it may help to click through and view these at actual size.)

The baseline is no longer consistent (especially comparing rounded letters like C and O to square ones like T), and there are noticeable artifacts in the small font. In all cases I am using createFont() in setup with a specific size, not adjusting it afterwards with textSize(). I’ve chosen a font that exaggerates the effect, but there are shifts and distortions with every font I use.

I know that there are always going to be some pixel-scale differences between rendering in the default renderer and P3D. But since typography is so sensitive to this stuff, are there any ways to minimize the font glitches that occur? Alternately, is there a way to use the default rendering engine on top of the 3D canvas, so I can have nice clean text regardless of what’s going on underneath?

Thanks.

Hi hi :slight_smile:

Does calling smooth(8) make any difference?

Here a way to combine P3D and JAVA2D:

PGraphics textLayer;
void settings() {
  size(640, 480, P3D);
  smooth(8);
}

void setup() {
  textLayer = createGraphics(width, height, JAVA2D);
  textLayer.beginDraw();
  textLayer.textAlign(CENTER, CENTER);
  textLayer.textSize(60);
  textLayer.fill(#FF0000);
  textLayer.text("nudiustertian", width/2, height/2);
  textLayer.endDraw();
}

void draw() {
  background(0);
  pushMatrix();
  translate(width/2, height/2);
  rotateY(millis() * 0.001);
  rotateX(millis() * 0.0001);
  box(200);
  popMatrix();

  hint(DISABLE_DEPTH_TEST);
  image(textLayer, 0, 0);
  hint(ENABLE_DEPTH_TEST);
}

image

1 Like

In 3D I always use textMode(SHAPE);

for a 2D HUD inside 3D see #9 here 25 life saving tips for processing (blogpost) - Processing Forum

Remark

also, for 3D I use lights(); and a function to avoid clipping

Thank you! This is a big help, and works perfectly.

Now the only annoying part is that most of my project is 2D graphics, with only a few small 3D aspects, and apparently I can only run a JAVA2D PGraphics on top of a P3D sketch – not the other way around. So now I have to go through and change every single line of my program, except for the handful of 3D transformations, to textlayer.something :expressionless:

1 Like

Hello,

Keep at it!

I just played with the code @hamoid provided:


boolean toggle;

void settings()
  {
  size(600, 600, P3D);
  //smooth(8);
  }

void setup() 
  {
  textAlign(CENTER, CENTER);
  textSize(100);
  }

void draw() {
  background(0);
  translate(width/2, height/2);
  
  pushMatrix();
  //translate(width/2, height/2);
  rotateY(frameCount * TAU/360);
  rotateX(frameCount * TAU/360);
  fill(128);
  box(200);
  popMatrix();

  //At end of draw();

  if(toggle)
    {
    //textMode(SHAPE);
    hint(DISABLE_DEPTH_TEST);
    fill(#FF0000);
    rotate(45*TAU/360);
    text("nudiustertian", 0, 0);
    hint(ENABLE_DEPTH_TEST);
    }
  else
    {  
    // This seems to work also.
    // I found this in my notes...
    ortho();
    fill(#FF0000);
    rotate(-45*TAU/360);
    text("nudiustertian", 0, 0);
    perspective();
    }
  }
  
void keyPressed()
  {
  toggle = !toggle;
  }

:)

1 Like

Hello @macwarrior,

Are you using a mac?

Can you provide a few lines of code (an MCVE) to reproduce your original issue?

I am just curious and want to try it on my W10 PC.

:)

1 Like

I am using Windows 10 as well. The name is an old one I’ve been using since the 1990s :slight_smile:
However, here’s a cut down version of what I used to make the example screenshots.

The font is freely available at VCR OSD Mono Font | dafont.com

PFont small, smaller;

color bg = #000000;
color fg = #ff0000;

void setup() {
  size(800, 480);
  //size(800, 480, P2D);
  //size(800, 480, P3D);
  
  hint(ENABLE_STROKE_PERSPECTIVE);

  small = createFont("VCR_OSD_MONO_1.001.ttf", 30);
  smaller = createFont("VCR_OSD_MONO_1.001.ttf", 24);
}

void draw() {

  background(bg);
  stroke(fg);
  strokeWeight(2);
  pushMatrix();
  translate(width/2, height/2);
  rotateX(radians(75));
  rotateY(radians(mouseX/4));

  for (int i = -10; i < 10; i++) {
    line(i*50, 0, i*50, 500);
  }
  for (int i = 0; i < 10; i++) {
    line(-400, i*50, 400, i*50);
  }

  line(-400, 0, 400, 0);
  popMatrix();
  
  noStroke();
  fill(#FFFFFF);
  textAlign(CENTER);
  textFont(small);
  text("AUTOMATIC CUCKOO CLOCK 01234567890", width/2, 100);
  textFont(smaller);
  text("AUTOMATIC CUCKOO CLOCK 01234567890", width/2, 130);
}

void keyPressed() {
  saveFrame();
}

Hell @macwarrior,

I was curious and wanted to compare outputs:

PFont small, smaller;

PGraphics pg;

boolean tog1, tog2;

color bg, fg;

void settings()
  {
  //size(800, 480);
  //size(800, 480, P2D);  
  size(800, 480, P3D);
  //noSmooth();
  //smooth(2);
  }


void setup() 
  {
  small = createFont("VCR_OSD_MONO_1.001.ttf", 30);
  smaller = createFont("VCR_OSD_MONO_1.001.ttf", 24);
  
  pg = createGraphics(width, 200); //Could also try P2D and P3D here
  
  if (tog1)
    {
    bg = color(0);
    fg = color(255);
    }
  else
    {
    bg = color(255); 
    fg = color(0);
    }
    
  pg.beginDraw();
  pg.fill(fg);
  pg.textAlign(CENTER);
  pg.textFont(small);
  pg.text("AUTOMATIC CUCKOO CLOCK 01234567890", width/2, 100, 0);
  pg.textFont(smaller);
  pg.text("AUTOMATIC CUCKOO CLOCK 01234567890", width/2, 130, 0);
  pg.endDraw();
  
  println(frameCount);
  }

void draw() 
  {
  background(bg);
  
  //if(frameCount%60 ==0) println(frameCount);
  
  stroke(fg);
  line(mouseX, 0, mouseX, height);
  
  noStroke();
  fill(fg);
  textAlign(CENTER);
  textFont(small);
  text("AUTOMATIC CUCKOO CLOCK 01234567890", width/2, 100, 0);
  textFont(smaller);
  text("AUTOMATIC CUCKOO CLOCK 01234567890", width/2, 130, 0);
  
  textMode(SHAPE);
  fill(fg);
  textAlign(CENTER);
  textFont(small);
  text("AUTOMATIC CUCKOO CLOCK 01234567890", width/2, 200, 0);
  textFont(smaller);
  text("AUTOMATIC CUCKOO CLOCK 01234567890", width/2, 230, 0);
  textMode(MODEL);
  
  image(pg, 0, 200);
  }

void keyPressed()
  {
  tog1 = !tog1;
  frameCount = 0; 
  setup();
  }

You can toggle the background\foreground color and there is a line that moves with the mouse.

noSmooth() needs to be set in settings() in my example; it will end up there in the end when you run it. See references for details.

smooth() has different defaults depending on the renderer used:
https://processing.org/reference/smooth_.html

There are more combinations to try… my exploration ends here for now.

:)