depthTest of text elements

Hi. I have some UI elements in my app, that I would like to avoid intersect with geometry. The UI compoent is made up of 3 Elements - two who are of type ELEMENTTYPE_IMAGE and one of type ELEMENTTYPE_TEXT.

I’ve set depthTest = false on the materials of the image elements, but how can I achieve the same result on the text element?

Regards

  • Björn

There could be better solutions. But one option would be to create a new Layer, that renders after the World layer, and make it clear depth buffer Layer | PlayCanvas API Reference

1 Like

I tried what I interpreted as:

  1. Created a new layer called Hotspots. Placed it last (transparent) in the render order list under settings

  2. Put all my three Elements on this new Layer (together with being on UI and Texts)

  3. Added a HotspotHandler script to do this on Initialize:

 // Clear the depth buffer on hotspot layer
    var layerComposition = this.app.scene.layers;
    var hotspotLayer = layerComposition.getLayerByName(this.hotspotLayerName);
    
    if  (hotspotLayer !== null) {
        hotspotLayer.clearDepthBuffer = true;
    }

this is still the result:
image

Hi @bjorn.syse,

Seems to work for me, check this sample project and here is the layers arrangement:

var DepthText = pc.createScript('depthText');

// initialize code called once per entity
DepthText.prototype.initialize = function() {

    const layer = this.app.scene.layers.getLayerByName('Text');
    layer.clearDepthBuffer = true;
};

image

https://playcanvas.com/editor/scene/1283744

Ah, thanks for having a look. Your example does work. But it’s using the built in Layer Text. I wonder if that makes a difference. I modifed your example slightly to make it similar to my setup, using a nested image element with a text element. I came to the conclusion that i can make it work if I place my things on UIand Textlayers respectively and then turn off depthClear for both of them like so:

DepthText.prototype.initialize = function() {

    const layer1 = this.app.scene.layers.getLayerByName('UI');
    layer1.clearDepthBuffer = true;
    
    const layer2 = this.app.scene.layers.getLayerByName('Text');
    layer2.clearDepthBuffer = true;
};

However, I never got this to work by creating and using one of my custom new layers in the same fashion. Did you?

modified example:

https://playcanvas.com/editor/scene/1283751

I am going to take a look, just note, there is no built-in layer named Text. I’ve created it and added the transparent sublayer to the layers list.

I don’t think you need to mess with the UI layer, @bjorn.syse try reordering your Text layer so it comes just after the World transparent layer.

ah, ok. Well

Hehe, here comes the next problem:

image

This is probably not so great.

Yeah, if there is no depth test that’s to be expected.

@mvaligursky any idea how you would approach this?

So the problem why we can’t use the same solution as on the Image elements is the text elements don’t have a Material exposed, right?

I would have either:

  • A second camera that clears the depth buffer, renders only the world UI layers and renders after the main camera
  • On the layers for the for the world UI, set it to clear depth buffer.
1 Like

Does the UI have to be in 3D space?

Another option might be to us 2D screen elements with corresponding entities in the 3d space. That way you could just check if the world entity was visible and screenToWorld the position of the hotspots over the appropriate spot on the geometry.

1 Like

Quick example of option two: https://playcanvas.com/editor/scene/1283769

2 Likes

Hmm that looks perfect! Thanks @yaustar

Wonder why I couldn’t get that to work. Perhaps that 3D screen element in the root is essential?

Ah, now I see. I probably forgot to add the new layer to my camera alltogher :smiley:

2 Likes

Aha, welcome to the club, that’s the commonest of the mistakes :smiley:

Yes, it’s not my first time :slight_smile:

1 Like