[SOLVED] Wall of text - problem with texture

I would like to create a “wall of text” which is just a plane with some lines of text on it. I have been successful in doing this in the html canvas however when applied as a texture it gets somehow messed up. The text only appears in the upper left hand corner (not clamping?) and the first half of each line is being cut off. It also appears slightly grainy to me.

While I have you, do you have any suggestions for how to make a marquee for scrolling text? My first thought is to just create new texture and upload it every frame. That seems a little sluggish but it doesn’t seem like CSS would apply here.

https://playcanvas.com/project/677177/overview/text

https://www.w3schools.com/code/tryit.asp?filename=GDO27CGFPUFP


Text.attributes.add('text', { type: 'string', default: 'Hello World'});

Text.prototype.initialize = function () {
    // Create a canvas to do the text rendering
    this.canvas = document.createElement('canvas');
    this.canvas.height = 512;
    this.canvas.width = 512;
    this.context = this.canvas.getContext('2d');

    this.texture = new pc.Texture(this.app.graphicsDevice, {
        format: pc.PIXELFORMAT_R8_G8_B8,
        autoMipmap: true
    });
    this.texture.setSource(this.canvas);
    this.texture.minFilter = pc.FILTER_LINEAR_MIPMAP_LINEAR;
    this.texture.magFilter = pc.FILTER_LINEAR;
    this.texture.addressU = pc.ADDRESS_CLAMP_TO_EDGE;
    this.texture.addressV = pc.ADDRESS_CLAMP_TO_EDGE;

    this.updateText();

    var material = this.entity.model.material;
    material.emissiveMap = this.texture;
    material.opacityMap = this.texture;
    material.blendType = pc.BLEND_NORMAL;
    material.update();
    
    this.on('attr', function (name, value, prev) {
        this.updateText();
    });
};

Text.prototype.updateText = function () {
    var ctx = this.context;
    var w = ctx.canvas.width;
    var h = ctx.canvas.height;

    // Clear the context to transparent
    ctx.fillStyle = 'black';
    ctx.fillRect(0, 0, w, h);

    // Write white text
    ctx.fillStyle = 'white';
    ctx.font = 'bold 24px Verdana';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    
    var textRemaining = this.text.toString();
    var i = 1;
    while (textRemaining.length > 0) {
      var textLine;
      if (textRemaining.length < 50) {
          textLine = textRemaining;
          textRemaining = "";
      } else {
        textLine = textRemaining.slice(0, 50);
        textRemaining = textRemaining.slice(50);
      }
      ctx.fillText(textLine, 10, 32 * i, w - 20);
      if (32 * i > w) break; // too many lines, omit the rest
      i++;
    }

    // Copy the canvas into the texture
    this.texture.upload();
};

Does this text need to be on a plane in 3D space?

Yes, that’s what I’m aiming for.

Hmmm, I would consider using a UI screen in world space and a combination of masking a text element that moves along it’s local axis.

2 Likes

I have solved the problem in a certain way. I used html2canvas to snapshot a div as a canvas element and apply it to the material.

https://playcanvas.com/project/677265/overview/html-tex

I did also try using an element and a screen which did work as expected. I was at the same time looking for general ways to represent html in 3d space so I guess I overlooked the more direct approach (not that I knew about it, thanks!).

1 Like