Issue with text displaying and materials

I’m having trouble trying to display text on a plane with a material. I get the error “Can not read property material of undefined”, but it’s attached as a component in my entity.

here’s the script ( copied from another project , a tutorial about text displaying : https://playcanvas.com/project/362231/overview/tutorial-canvas-text )


var Text = pc.createScript('text');

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 = 128;
    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();

    console.log(this.entity.model);
    
   var material =  this.entity.model.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 70px Verdana';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText(this.text, w / 2, h / 2);

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

Furthermore, after some tinkerings (sometimes) i’ve beeen able to display text in the plane, but it’s the same one all the time. IE: having 3 objects, each one with the text script attached, the three of them will show the text of the last object added to the scene.

Here’s the link to my project : https://playcanvas.com/project/613153/overview/udg

Hey everyone,

For those who are still facing this issue, this is because all of the label entities with the same material will display the text of the most recently added one. To fix this, the material needs to be cloned and the cloned material added each time the text.js script is initialized. You can modify the initialize method as follows -

Text.prototype.initialize = function () {
    // Create a canvas to do the text rendering
    this.canvas = document.createElement('canvas');
    this.canvas.height = 128;
    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 materialOrg = this.entity.model.material;
    var matNew = materialOrg.clone();
    this.entity.model.meshInstances[0].material = matNew;

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

The rest will then work as expected.

I hope this helps!

2 Likes

and also, if you use Render component, and not Model component, all this.entity.model need to be changed to this.entity.render

3 Likes