[cesium-dev] Labels visibly cross another objects

This is actually a very difficult problem because you don’t want labels to show through the earth or for a label far away to be in front of an object that is close to the camera. You’re best bet for now is to have labels that are offset from the object they are labeling. You can do this by setting the eyeOffset of the label to have a Z value (I forget it it needs to be positive or negative).

Thank you Matthew, I’ll play with eyeOffset.

Just my personal opinion: label must not partitially cross another objects, i.e. it must be fully visible or fully invisible. May be crosing Earth horizon is separate case. And I absolutely agree: the problem in whole is very difficult and probably has no universal solution.



Right now the visible test is done pixel-by-pixel for labels. We are considering doing it, instead, using just the label’s center point for all pixels. In practice, this is not quite as easy as it sounds but is something I expect we’ll experiment with.



Thanks for explanations. I thought that Label is a textrured rectangle. It was because I don’t know WebGL and its bottlenecks well :slight_smile: .


2 strange things in the Sandcastle:

  1. “Volumes” example. Volumes-ellipsoids disappear when I slightly rotate the globe.

  2. “Picking” example. If scene.globe.depthTestAgainstTerrain = true, Label and Billboard sink deeply into the ground.

It was on desktop computer with good nvidia card.

I couldn’t experiment with Label.eyeOffset yet****as Matthew Amato recomended. May be something can be corrected with it.

I have a similiar issue with the depthtest. Keep hoping each new version solves it but not sofar.

When DepthTestAgainstTerrain is on, labels, billboards, plotlines and areas disappear & reappear at certain heights, but my moving ellipsoids only show the portion above the earth. When depthTest is off, ellipsoids are not pretty but at least I don’t ‘lose’ sight of the others…




If you come up with a simpler idea than the suggested one, please let me know.




I’ve accidentaly posted private message to you, I’m not sure you will see it. I repeat it here.

I had to switch to another method. I need a bit more complicated info object and use html div with table inside instead of Label or Billboard. It is placed over Cesium canvas. In my code I change its content, visibility, transparency and move it with the globe sinchronously. It’s a temporary solution, not very good, very limited, but it works in my case. May be it can help you too.


Hi Alexei, I use the same technique and display a popup menu even, when one clicks on the billboard to which the ellipse is attached. Works really well for our purposes. However my main issue is with the depthtest versus using Terrain to evaluate visibility. Interwoven with 2D and the technique used to move the ellipse (essentially attaching the modelmatrix to the primitive not the geometry instance). All these methods and settings are inter-related and I have had to choose the lesser of the resulting evils. See my post https://groups.google.com/forum/embed/?place=forum%2Fcesium-dev&showsearch=true&showpopout=true&hideforumtitle=true&parenturl=http%3A%2F%2Fcesiumjs.org%2Fforum.html&afterlogin=&pli=1#!topic/cesium-dev/fHVc4gVI6vI

Thanks though!



Hi Rencia,

Sorry for late comment.

Your Sandcastle code is for old version, I tested another sample. I found that Label and Billboard don’t work well when depthTestAgainstTerrain is on. At low heights when Earth surface looks plane, eyeOffset parameter helps well. Negative z-offset makes label or billboard always visible. The larger is camera height, the larger eyeOffset value must be for that. Universal eyeOffset value doesn’t exist because large offset at low height places billboard behind camera making it invisible.

Billbosrd and Label are important objects, but their implementation is not obvious (at least for me).


Hello Alexei, sorry to interrupt this thread, but I have been searching for an example of exactly what you have done (creating a more complicated info object using HTML vs the billboard/labels). Would you mind sharing a simple example of what you've done to accomplish that?


  • I can’t make a complete working example now, I’ll try to illustrate key things.

  • Please take into account that I’m new to web development.

  • My element works in narrow range of heights and distances, I hide it when it’s out of the range, so I didn’t need to think about a number of interesting things such as crossing the horizon.

Feel free to ask, I will try to share more details if necessary.

  1. The element below will be our custom billboard.

In html section,


is positioned over Cesium canvas. Fragment of css for it:

#myBillboard {

position: absolute;

z-index: 2; /* it must be higher then canvas */

background-image: url(‘images/bb-bk.png’ ); /* in my case this is a balloon-shaped semi-transparent PNG */

background-repeat: no-repeat;

display: none; /* initially hidden */

pointer-events: none; /* transparent for mouse events */

/* … */


  1. Jacascript. Somewhere close to the beginning of code

var bb = document.getElementById(‘myBillboard’); // bb is my billboard

// position in world (Cartesian3) coordinates.

bb.position = Cesium.Cartesian3.fromDegrees(50, 50, 0, ellipsoid);

bb.scrx = -99; // screen coords. initialized by “impossible” value

bb.scry = -99;

// Above parameters: position, scrx and scry were added to the object for futher use. position

// can be changed at any moment

  1. We need to correctly place our bb on the screen when camera changes. AFAIK Cesium API doesn’t provide special camera tracking events, I use timer for this.



// transfer bb.pos (world coord) to screen coord.

var newScr = Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, bb.pos);

// round off (floor())

newScr.x |= 0;

newScr.y |= 0;

// work only if something changed

if ( bb.scrx != newScr.x || bb.scry != newScr.y )


bb.scrx = newScr.x;

bb.scry = newScr.y;

// move the bb.

// Our billboard has a hot spot which points exactly to its world position (bb.pos) on the screen.

// We set screen coordinates of bb’s left-top corner and have to calculate them.

// bbWidth and bbHeight are numerical constants in my case, I set them explicitly at start.

// In my case bb has a baloon-like semi-transparent background image. Its hotspot is in the

// middle of bottom edge of the element’s rectangle:

bb.style.left = (bb.scrx - bbWidth / 2) + ‘px’;

bb.style.top = (bb.scry - bbHeight) + ‘px’;




  1. To turn bb visiblility on: bb.style.display = ‘block’;

and off: bb.style.display = ‘none’;

I forgot to add. I consider this solution as temporary. In my tests, Html billboard motion is very good, smooth in IE, satisfactory - in Firefox and terrible in Chrome. I would prefer inverse order :slight_smile: . It probably depends on maximum allowed frequency of timer in different browsers.


Thanks Alexei


Using viewer.clock.onTick.addEventListener() instead of setInterval() solves the problem in my case. The html billboard and land moved asynchronously when I used setInterval().