TextBlock on Plane, Cannot show all text? Dont understand why

So I have simplified the code, as simple as I can make it
I do not understand why the more letters that are in the text, the wider each character.
And I dont understand at all how the actual letters dont fit on the texture if there are a lot of them
Why are short texts, super thin and tiny?

More directly :slight_smile:
How do I get accurate sizes for these textures. I thought using a div to calculate the “real size” of the string as rendered in the font was super clever :slight_smile: Using Courier doesnt seem to make any difference.

Possibly relevant questions:
So I have used Courier Prime in both the Web Page and the TextBlock. The only other thing I can think of is font-weight

nodes.textSizer.css("font-family", "Courier Prime");
nodes.textSizer.css("font-size", "17px");
nodes.textSizer.css("font-weight", "normal");
nodes.textSizer.text("text");

var makeTextPlane = function(text, color, size) 
    {
      // size is an arbitrary multiplier that scales the entire model. Useful for controlling
      //   the actual visual experience of fog
      
      // textSizer is a div with { width: fit-content }
      nodes.textSizer.text(text);
      
      // This calculation seems to give the right width to convert from the div width to the 3d space width
    let textLength = (nodes.textSizer.width()/size)*2;


      let textureWidth = textLength;
      let textureHeight = size * 2;

      let plane = BABYLON.MeshBuilder.CreatePlane("plane", {"height": textureHeight, "width": textureWidth}, scene);
      
      var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateForMesh(plane);//),{"height": 10, "width": 1000});

      var text1 = new BABYLON.GUI.TextBlock();
      // text1.text = text;
      text1.resizeToFit = true;
      // text1.background ="yellow";
      // text1.outlineColor = "white";
      // text1.outlineWidth = size;
      text1.color = "white";
      text1.fontSize = 17*size;
      text1.fontFamily = "Courier Prime";
      text1.fontWeight = "normal";
      // text1.width = textureWidth;
      // text1.height = textureHeight;
      // text1.resizeToFit = true;
      advancedTexture.addControl(text1);  

      // advancedTexture.rootContainer.scaleX = window.devicePixelRatio;
      // advancedTexture.rootContainer.scaleY = window.devicePixelRatio;

    // plane.lookAt(camera.position);
      return plane;
     };

1 Like

And this is is what I get if I just set textLength = 30

However there are always only 12 characters displayed maximum, even though the actual letters sizes are constant and reasonable and look normal.

I simply have no idea what textBlock and Mesh and AdancedTexture are doing to produce this.

And this code, produces the screenshot below???
The difference here is that I have made the width of the texture fixed at 30, and changed the font size to 120 to make the text fit inside the texture.

I have absolutely no idea how that make sense.

var makeTextPlane = function(text, color, size) 
    {
      // size is an arbitrary multiplier that scales the entire model. Useful for controlling
      //   the actual visual experience of fog
      
      // textSizer is a div with { width: fit-content }
      nodes.textSizer.text(text);
      
      // This calculation seems to give the right width to convert from the div width to the 3d space width
      let textLength = 3 * size;//(nodes.textSizer.width()/size)*2;


      let textureWidth = textLength;
      let textureHeight = size * 2;

      let plane = BABYLON.MeshBuilder.CreatePlane("plane", {"height": textureHeight, "width": textureWidth}, scene);
      
      var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateForMesh(plane);//),{"height": 10, "width": 1000});

      var text1 = new BABYLON.GUI.TextBlock();
      text1.text = text;
      // text1.resizeToFit = true;
      // text1.background ="yellow";
    text1.outlineColor = "white";
    text1.outlineWidth = size;
      text1.color = "white";
  text1.fontSize = 12*size;
      text1.fontFamily = "Courier Prime";
    // text1.fontWeight = "bold";
    // text1.width = textureWidth;
    // text1.height = textureHeight;
      // text1.resizeToFit = true;
      advancedTexture.addControl(text1);  

      // advancedTexture.rootContainer.scaleX = window.devicePixelRatio;
      // advancedTexture.rootContainer.scaleY = window.devicePixelRatio;

    // plane.lookAt(camera.position);
      return plane;
     };

Any chance you can reproduce the problem in a PG?

Without seeing the whole code in action it’s hard to help because the problem could be a specific interaction between the gui and something else…

1 Like

Thank you :slight_smile:

https://playground.babylonjs.com/#8VY1ME#16

Im utterly lost as to what is happening. Why do two textures with different text, but the same width, display the actual characters as the same size, but if I make the texture wider to accomodate more characters, it just makes the characters wider?
The only thing that makes any difference here is the font size. ??!!??

Specifically, why are example numbers 3 and 4 showing the text at the same character size? Rather than squashing the characters to fit in the space provided? resizeToFit = true doesnt make any difference.

I dont understand why setting the fontSize to something constant, and then making the texture wider doesnt give space for more characters.

How is it possible to make text “work”, if at "font size 12 it is only posisble to get 10 characters on a mesh regardless of how big the mesh is, and I have to use font-size 8 to get 20 characters? Is this the design? Can someone explain it to me?

As far as I understand font rendering into 3D, one makes the string in the browser, paints it onto a canvas, gets the bitmap from the canvas and paints that onto the surface as a texture. I would expect that by making the texture size proportional to the text length, I should be able to get perfectly rendered text. Here it seems I have to pick maximum number of characters I want to see in a string? and then pick a font-size, and then if at some point I decide I need more characters in one of my strings, I have to go back and resize the height of all the other meshes? That cant be the design. So I must be doing something wrong lol :slight_smile:

the only thing I can think of that makes sense, is that the AdvancedDynamicTexture is only taking in to account the height of the mesh that it is applied to.

It does give you more room if you make the texture wider.

Your example is a bit complicated as you are performing some computation I don’t really understand.

I have simplified it to demonstrate that if you increase the texture size you will have more room for the text:

https://playground.babylonjs.com/#8VY1ME#17

The first plane is using a texture of 1024 pixel width and the second one a texture of 2048.

Note that in your sample you never change the texture dimensions:

var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateForMesh(plane);//),{"height": 10, "width": 1000});

Width/height of the texture comes after the plane parameter.

Oh thank you so much :slight_smile: !

I was using an options dict for CreateAdvancedTexture height and width.

here is the code as I was trying to achieve:

https://playground.babylonjs.com/#8VY1ME#21

What you can see is we are using a DIV element on the page to calculate the ratio of height to width of the rendered text (in a div), and then using that ratio.

We choose the Height of the plane we wish to see visually, and then we get an accurate width for the plane to render the texture using the ratio discovered by the browser. This will work with any font, obvs :slight_smile:
Looks lovely.

Note the font size / weight, decorations, etc, should be the same in the browser DIV element, and the TextBlock element. Having a higher font size in both gives a higher fidelity bitmap.

maybe there is a way to do this that is already built in some how?

thank you so much for taking the time to answer me :slight_smile:

The ADT is using a canvas 2D to draw things, so I think font sizes used do draw in this canvas do match font sizes in the regular HTML pages. However, when the texture is drawn over a mesh, it won’t keep its original size, except if the mesh screen dimensions match exactly the texture pixel dimensions.

Don’t know if this is of any use Use Dynamic Texture - Babylon.js Documentation

1 Like

So here, this is what I mean: https://playground.babylonjs.com/#8VY1ME#33

so I know that the ADT is using a canvas to render the bitmap. And rendering the text in the browser first off with the options supplied to TextBlock.

What I am saying is that the ratio of width to height is also calculated by the browser, when it renders the text in a DIV. this calculation is non trivial for non-fixed width fonts. The only way to get an accurate width to height ratio is to actually draw the text.

This is already happening.

What I have done, you can see here, is create a DIV to render the text in to, and then got the height / width ratio.

The Font Size of the DIV and the TextBlock need to match to get an accurate rendering.

The Higher the Font Size, the higher the resolution of the rendered text.

There are various rounding errors, you can see as the texts are slightly different widths as the font size increases. But if you pick a constant font size for your renderings, then everything else should work fine.

It seems these tools could easily be added to the TextBlock object? I dont know. Is this a closed sourcee project? Its very good. Thank you :slight_smile:

This is an open source project, everyone can participate. The repo is here: GitHub - BabylonJS/Babylon.js: Babylon.js is a powerful, beautiful, simple, and open game and rendering engine packed into a friendly JavaScript framework.

However, I’m not sure we need to update the core code as the doc @JohnK has linked to seems to fit the bill to me (it is describing how to compute the ratio accurately).

Yes, thats what I thought I was looking for. I could tell it would be documented somewhere :slight_smile:

Ill have a look at the repo and see if I can contribute anything useful Thank you