CesiumGS / cesium

An open-source JavaScript library for world-class 3D globes and maps :earth_americas:
https://cesium.com/cesiumjs/
Apache License 2.0
12.76k stars 3.46k forks source link

Z-Ordering of entity collection #4108

Open tfili opened 8 years ago

tfili commented 8 years ago

It would be nice to be able to change the render order of entities. Right now we have to tweak the eyeOffset which needs to change based on camera distance.

hpinkos commented 7 years ago

This is probably one of the most frequently requested things on the forum. Also requested in #53

pjcozzi commented 7 years ago

CC #3647

shunter commented 7 years ago

cc AnalyticalGraphicsInc/czml-writer#20

hpinkos commented 7 years ago

Related: #4878 #4695

hpinkos commented 7 years ago

Also reported here: https://groups.google.com/forum/?hl=en#!topic/cesium-dev/iyNHsibp2eI

smills2929 commented 7 years ago

+1. I'd love to see this!

hpinkos commented 7 years ago

Also requested here: https://groups.google.com/forum/?hl=en#!topic/cesium-dev/p_TufXEFwTA

emackey commented 7 years ago

Thinking about a possible implementation for billboards: https://groups.google.com/d/msg/cesium-dev/7CHDGRyJvwc/S55fUJ8XCAAJ

schitzN commented 6 years ago

push

Seems like this is still an issue. We have the same problem with labels drawn underneath polylines.

hpinkos commented 6 years ago

Hi @schitzN, this hasn't been addressed yet. But stay tuned! We're starting work on this in the next month

ggetz commented 6 years ago

@hpinkos Will these changes also apply to billboard/lablel/polyline collections?

See on the forum: https://groups.google.com/forum/#!topic/cesium-dev/ywyFR5GSi_c

hpinkos commented 6 years ago

@ggetz the changes I'm working on this round are specifically to address z-ordering in 3D, so I won't be making changes to billboards/labels because they are ordered spatially by their 3D position. We will have support for ordering polylines on the earth surface.

erezy commented 6 years ago

@ggetz Thanks! @hpinkos changing the order of the primitives collections in 2D worked in the past (V 1.21) I don't know why it stopped working. Do you know when the issue will be resolved?

hpinkos commented 6 years ago

Thanks @erezy, I didn't realize this was a regression. I've opened a separate issue so we can look into fixing it: #6569

eatjhuapl commented 6 years ago

Will these changes also apply to rendering GeoJsonDataSource ?

hpinkos commented 6 years ago

@eatapl we haven't hooked this up to GeoJson because I couldn't find anything in the GeoJSON spec that can be used to specify polygon ordering. Does GeoJSON have a property used for ordering that I missed? Thanks!

killroy42 commented 6 years ago

Is there a workaround currently for at least drawing polylines below billboards? I'm implementing my own z-ordering where I can, but I don't know how to interact with the render pipeline for the parts of a single entity.

hpinkos commented 6 years ago

@killroy42 can you provide a short code example to reproduce the problem you're seeing?

killroy42 commented 6 years ago

Well, just create an entity with a billboard image and a path. The project I'm working on: http://rolexmiddlesearace.com/trackerpt/

If you tilt the camera back and forth you see that the path switches places with the billboard icons.

hpinkos commented 6 years ago

@killroy42 I see what you're talking about. It's tricky to order billboards in 3D because you generally want them to order spatially (ie a billboard that is closer to the camera will draw on top of a polyline that is drawn in the distance). This is part of the reason why we have not added a z-index property to billboards.

You can try setting a negative z value to eyeOffset: billboard.eyeOffset = new Cesium.Cartesian3( 0, 0, -100) This makes the billboard draw as if it is closer to the camera, so it should push it above the polylines.

killroy42 commented 6 years ago

Thanks, I'll try that. Is there an easy method to have an icon align horizontally with the ground, rather then vertically with the plane of the camera? As you can see, I really would like flat icons on the ground, than standing upright in the air.

hpinkos commented 6 years ago

@killroy42 no sorry, billboards aren't really designed to work that way. You could try replacing the billboards with a rectangle using an image for the material. This might have slightly poorer performance though depending on how many you have in the scene at a time.

Zpeugh commented 5 years ago

I've got entities that I needed to disable depth testing (set disableDepthTestDistance to Number.POSITIVE_INFINITY), but I also have labels that are going on top of these entities, and the shape entities are getting rendered on top of the labels always. Is there any way to make labels always render last? Or is this still a WIP? Attached an example image. z_index_isue

hpinkos commented 5 years ago

@Zpeugh It's hard to tell exactly what's going on in the picture you posted, so I'm not quite sure why the label is rendering behind the geometry you have there. I would recommend applying an eyeOffset: new Cesium.Cartesian3(0, 0, <some negative value>) to your labels. This makes the label draw as if it's closer to the camera. All billboards and labels layer spatially, so things closer to the camera layer in front of things further away.

Zpeugh commented 5 years ago

I can explain the picture a bit more. The background is a B3DM texture mesh. The teal lines are all polyline entities with depth testing disabled. The labels are created with these parameters: { position: cartesianPoint, showBackground: false, font: (ANNOTATION_FONT_SIZE scaleFactor) + "px 'Source Sans Pro', sans-serif", scale: 1.0 / scaleFactor, style: Cesium.LabelStyle.FILL_AND_OUTLINE, fillColor: Cesium.Color.WHITE, outlineColor: new Cesium.Color(0, 0, 0, 1), outlineWidth: 3.0 scaleFactor, horizontalOrigin: Cesium.HorizontalOrigin.CENTER, verticalOrigin: verticalOrigin, disableDepthTestDistance: Number.POSITIVE_INFINITY, fontSize: ANNOTATION_FONT_SIZE }

I have already tried adding eyeOffset: new Cesium.Cartesian3(0, 0, -100000) and it only makes the labels invisible until you scroll well away from the surface of the globe. And even then, the polyline entities are still rendered on top of the label.

hpinkos commented 5 years ago

The teal lines are all polyline entities with depth testing disabled

This is what's causing the problem. If depth testing is disabled, it's completely ambiguous what is "closer" to the camera and should be rendered on top.

Zpeugh commented 5 years ago

Okay that makes sense, but I need to have my shape entities always show through the B3DM's underneath or else I get something like this. (The label does show on top when the polyline entity depth testing is turned back on, as expected). Any ideas on how to get the proper rendering z-indexing in this scenario? Or am I SOL? depth_test_enabled

hpinkos commented 5 years ago

@Zpeugh you might be able to do something with the classification options. See https://cesiumjs.org/Cesium/Build/Apps/Sandcastle/?src=Polylines%20on%203D%20Tiles.html&label=3D%20Tiles

Zpeugh commented 5 years ago

Alright thanks for your time. I will poke around with classification options. I'll post my answer here if I figure out a solution for my problem.

ladislavhorky commented 5 years ago

+1 for me. Same issue with polylines rendering over labels, polylines left untouched, labels having disableDepthTestDistance: Number.POSITIVE_INFINITY.

When setting polyline material and depthFailMaterial to be different, I discovered that parts of polyline covering the labels are rendered using depthFailMaterial event through the surrounding polyline is rendered with material. This would suggest that disableDepthTestDistance works for depth test itself but the result is not honored in this case.

hpinkos commented 5 years ago

@ladislavhorky Could you put together a Sandcastle example to reproduce that?

ladislavhorky commented 5 years ago

@hpinkos here it is. You only need to turn it a bit to get some label in the town square to cross transparent polyline.

hpinkos commented 5 years ago

@ladislavhorky The lines are drawing on top of the labels because you set a depthFailMaterial. That is working as designed. The depthFailMaterial colors the line when it fails the depth test, so it will always draw on top of the label when the label is in front of the line spatially. The lines look like they are rendering below the labels if I remove depthFailMaterial

ladislavhorky commented 5 years ago

@hpinkos I see, that makes sense. But then, is there some way to make the polylines visible through the terrain/3D tiles without setting depthFailMaterial and thus interfering with labels? Like maybe splitting labels and lines into separate datasources? The intended behavior is to make both labels and lines visible through the mesh with correct z-ordering much like in Zpeugh's example.

My best workaround so far is to use distanceDisplayCondition for labels to minimize the crosses and some transparency for polylines to make the crosses less visible.

hpinkos commented 5 years ago

I'm sorry @ladislavhorky, I don't have any workaround at this time

ladislavhorky commented 5 years ago

@hpinkos Thanks for your time anyway. I'll do with the transparency for now.

Maarondesigns commented 4 years ago

Was there ever a resolution found for this issue? I am getting different behavior depending on the alpha channel of polygon material as well. If the material has any transparency, the labels appear behind. If alpha is 1.0, label appears in front, but always behind polylines (GeoJsonDataSource stroke). See image on the left, green color has 1.0 alpha while other colors have less.

Also, in an unrelated issue, the individual letters of label text appear wonky/not-aligned if the text is smaller than about 17px (right image)

image

jony89 commented 4 years ago

@hpinkos , what is the roadmap regard this feature?

it is extremely needed, and it seems there is no workaround at the moment?

OmarShehata commented 4 years ago

@Maarondesigns thanks for pointing these out. These are potentially separate issues. The small font issue seems to have been working as of CesiumJS 1.62. I opened an issue for this here: https://github.com/AnalyticalGraphicsInc/cesium/issues/8474

For the outline ordering issue, I'm unable to reproduce this. Here's the Sandcastle I tried. You can toggle the material alpha = 1 vs alpha = 0.8 with the buttons. It seems that the stroke is always on top regardless. Are you able to share a Sandcastle example that reproduces it?

@jony89 there may be a workaround depending on what exactly you're trying to achieve. Feel free to open a Cesium forum discussion thread describing your use case.

Maarondesigns commented 4 years ago

I've circled back to this issue on a separate project. It seems like polylines render randomly above or below polygons and corridors with alpha less than 1.0. I am creating everything using the Primitive API. The project is my own version of the game RISK if you're interested: github

//country fill
let polygonPrimitive = new Cesium.Primitive({
        show: dontShow ? false : true,
        releaseGeometryInstances: false,
        geometryInstances: new Cesium.GeometryInstance({
          id: id + "_polygon",
          geometry: Cesium.PolygonGeometry.createGeometry(
            new Cesium.PolygonGeometry({
              polygonHierarchy: cartesian,
              height
            })
          )
        }),
        appearance: new Cesium.MaterialAppearance({
          material: new Cesium.Material.fromType("Color", {
            color: new Cesium.Color(
              fillColor[0],
              fillColor[1],
              fillColor[2],
              fillOpacity
            )
          })
        }),
        asynchronous: false
      });
//country border
let corridorPrimitive = new Cesium.Primitive({
          show: dontShow ? false : true,
          releaseGeometryInstances: false,
          geometryInstances: new Cesium.GeometryInstance({
            id: cid,
            geometry: Cesium.CorridorGeometry.createGeometry(
              new Cesium.CorridorGeometry({
                positions: p,
                width: 8000,
                extrudedHeight: height + 10000
              })
            )
          }),
          appearance: new Cesium.MaterialAppearance({
            material: new Cesium.Material.fromType("Color", {
              color: new Cesium.Color(
                strokeColor[0],
                strokeColor[1],
                strokeColor[2],
                strokeOpacity
              )
            })
          }),
          asynchronous: false
        });
//path
let path = new Cesium.Primitive({
      releaseGeometryInstances: false,
      geometryInstances: new Cesium.GeometryInstance({
        id: id?id:"path",
        geometry: Cesium.PolylineGeometry.createGeometry(
          new Cesium.PolylineGeometry({
            positions,
            width
          })
        )
      }),
      appearance: new Cesium.PolylineMaterialAppearance({
        material: new Cesium.Material.fromType("PolylineDash", {
          color
        })
      }),
      asynchronous: false
    });

Changing the camera angle makes the dashed polyline pop in front of or behind the countries. Same behavior when corridor alpha<1.0. In image below corridor alpha is 1.0. image

Maarondesigns commented 4 years ago

@Maarondesigns thanks for pointing these out. These are potentially separate issues. The small font issue seems to have been working as of CesiumJS 1.62. I opened an issue for this here: #8474

For the outline ordering issue, I'm unable to reproduce this. Here's the Sandcastle I tried. You can toggle the material alpha = 1 vs alpha = 0.8 with the buttons. It seems that the stroke is always on top regardless. Are you able to share a Sandcastle example that reproduces it?

@jony89 there may be a workaround depending on what exactly you're trying to achieve. Feel free to open a Cesium forum discussion thread describing your use case.

I was able to reproduce in your sandcastle...This issue occurs when the polygon has extrudedHeight and then eyeOffset is used on the label to appear in front of it. SandCastle

It also occurs when you use a billboard with image: [ html canvas ], which I started doing to fix the alignment issue of the letters.

dzungpng commented 3 years ago

Another mention of this: https://community.cesium.com/t/on-2d-mode-polylines-are-always-on-top-of-labels/11451

aldenpoole commented 2 years ago

Is there still no good fix for this? Even setting an eyeOffset z value is a subpar solution. I am having such trouble getting my label entities to appear over my arcs. The arcs vary in height, and some of them get very high.

I should say - the labels are for other entities on the map and not related to the arcs at all.

Can there not be a flag to treat these label entities as such so that they are just rendered above everything else, regardless of height?

ggetz commented 1 year ago

Requested in https://github.com/CesiumGS/cesium/issues/10861

ggetz commented 1 year ago

Also reported in https://github.com/CesiumGS/cesium/issues/11097 and https://github.com/CesiumGS/cesium/issues/11074.

nikitakogan commented 1 year ago

Hello ,

I found an issue where I cant use polyline collection cause its overlaps billboard and there is no way to control the heights .

Here an example : https://sandcastle.cesium.com/#c=nVRbb9owFP4rVl4GgjoByigpRatopU3a1kpIe1n2YJwDWJg4sg0hq/rfd+wQSC/TpEV5OOfzd+7H5iozluwFFKDJDcmgIDMwYrelPzzWSgLu9ZnKLBMZ6CToPiUZIYZDBt9UCvHRYF4DdD67/37fv0uy5/Z1knEfIleylGhvXkZ5PMIzJSVwK1TWcjZJduJTlqatJ+JC5soIRzEkru1nTFuUWDagS622d7DSAOZWa1Z+BrFaW9P66UwJuRgNaS/qksGYDkfdXhR1a3xEoz7iV3Q4aOJXER06PppdvsJ7yO8P6eVHj/9q+6NCpHaNmQ28ZtaqiK3ewXNVz55pYvarO2bZHXDJNGAjkiBFPRZbtoIQTzuHrewmwfWJPhOaS8f8MOGVyA83SdCLkoDwspY0CkMnGKvVBlBbSMY3J+DCp4bwAKGlkBJFDSkq4ZR8OEd71LAUBx8NNbIHbbDbLgrtIRmTywxqa2vzOAyLoqDFgCq9CvtRFLn8a1J8wNFt3qX2xuNx6I8dGSlRfkCpPEl1rpeVuvZTPOvoPzY5467KXIMBvYckmDaqmO+WVRVJMHFJTZsNnVstshUensvtNBrdOTvwUwtDwjUwC8Susfd+5whkVtjy5PLeq1/cDCu/zRl3zkFdEv5OUe9A1KtdrVW92//Y7NabtWwf93KBc10optOYHF26z69W/CrN7vk8FweQc/EbOaOogTMpVhmktwdh4v9MyH1QwsNyacDGzUt/9tRCQ/wvnFll9Xx8NU7N8u8MzbXYYn/2x6adXof2X7r6smDHCrrBxNhSwrRO75PY5kpbstOyRWloYZtLHLUJFzu+AUu58e4dFRepYTpJxZ6I9Oadt5Hg2I27JMud9H3F3ZyEyH9jKhVLcSse8JZJVjraujf9WoGU0kmI6vuWVim5YPqV5z8

is there any way to solve it by code or its a bug?

@ggetz

ggetz commented 5 months ago

Also reported in https://github.com/CesiumGS/cesium/issues/11925.