Hide labels that go behind a gltf?

I’ve created labels and i am planning to hide them whenever they “go behind” or when the view is blocked by the gltf model what would be the easiest solution to achieve this?

My gltf:

loaderGB.load('./resources/map/land.gltf', function (land) {  
       landmass = land.scene;
       landanimate = land;

                    land.scene.traverse( function ( child ) {
                            if ( child.isMesh ) {
                                child.castShadow = true;
                                child.receiveShadow = true;
                                child.frustumCulled = false;
                        } );
                        land.scene.scale.set(9, 9, 9);
                        land.scene.position.set(0, -5, 0);

my labels:

                var hotspot = document.getElementById('death');
                hotspotLabel = new CSS2DObject(hotspot);
                hotspotLabel.position.set(-0.5, 0, -2);
                labelRenderer = new CSS2DRenderer();
                labelRenderer.setSize(window.innerWidth, window.innerHeight);
                labelRenderer.domElement.style.position = "absolute";
                labelRenderer.domElement.style.top = 0;


thanks for any help

it won’t be that easy, you will have to raycast towards the camera and see if something obstructs the line of sight. in the off chance you use three + react then it’s not even an after though: Mixing HTML and WebGL w/ occlusion - CodeSandbox

if not, here’s the full code, you need to fork css2d and re-purpose it using the raycast logic, drei/Html.tsx at 1de1854b88b4cf4e114aee7c366176fb8aead298 · pmndrs/drei · GitHub

I wouldn’t of thought raycasting would work with CSS2D ?

I expect the visibility issue to be most thoroughly solved by making the labels true 3D-objects, like textured planes. Maybe add some billboarding for better readability. I would also expect any raycasting to work out of the box for true 3D-objects.

1 Like

i don’t see any raycasting in three.js/CSS2DRenderer.js at 9db14dd2abd922874656c2f8d1e04c792fb0f594 · mrdoob/three.js · GitHub “ray” is not even mentioned. maybe im out of the loop and people are fetching css2d from elsewhere these days?

If I remember correctly, it’s you who brought up the topic of raycasting:

And from the TO’s naming of his labels as “hotspots” it’s not far-fetched to assume that he wants them to be clickable. So what are we talking about?

If css2d behaves like css3d I think there is no need for special code to implement occlusion, just like the the react example this can also work in ‘plain’ ThreeJS (most of the screens here are Iframes on css3d that have their own Html pages): What am I missing?
Scifi (threeml.org)

Here a quick example how it can work with the css3d object:

1 Like

The sandbox @drcmda shared has a really nice simple solution that could ported back to plain JS easily.

However it only works for rectangular occlusion and it’s all or nothing - either the HTML shows, or it is hidden. You can’t hide half of it behind a mesh and you won’t be able to use it to get a curved occlusion like the label behind the earth model.

It looks really good in that example because the HTML is placed exactly on a rectangular mesh. If you switch to a sphere or remove the rotation limits on the OrbitControls and view from underneath you’ll see the limitations.

If you need proper 3d occlusion I would try using a sprite or plane like @vielzutun.ch is suggesting.


This is the part where I initiate the renderers that work for the css3d to support occlusion. Maybe it also works for css2d?

			rendererCSS = new CSS3DRenderer();
			rendererCSS.setSize(innerWidth, innerHeight);

			// put the mainRenderer on top
			renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
			renderer.setClearColor(0x000000, 0);
			renderer.domElement.style.position = 'absolute';
			renderer.domElement.style.top = 0;
			renderer.domElement.style.zIndex = 1;
			renderer.setSize(innerWidth, innerHeight);


i am planning to hide them whenever they “go behind” or when the view is blocked by the gltf model what would be the easiest solution to achieve this?

that is raycasting, no? how else will you “hide” a label “behind” a model. you cast a ray towards the camera and if it intersects you hide the label. or are there any other ways to solve that?