I have multiple GeoJsonDataSource
objects that I want to put on a Cesium globe. The problem is that if they overlap, I get some z-fighting issues and I can't adjust their order.
Is there a way of specifying the order of DataSource
objects in a DataSourceCollection
?
For example, I'd like to have the green polygon on top of the red polygon using the following code:
var viewer = new Cesium.Viewer('cesiumContainer');
var red = Cesium.GeoJsonDataSource.load('map1.geojson', {
fill: new Cesium.Color(1, 0, 0, 1.0)
});
var green = Cesium.GeoJsonDataSource.load('map2.geojson', {
fill: new Cesium.Color(0, 1, 0, 1.0)
});
viewer.dataSources.add(red);
viewer.dataSources.add(green);
However, the result looks like this:
I've noticed that if I adjust the alpha argument to less than 1.0
, I can fix the z-fighting, but the order still does not get addressed.
Cesium has added a zIndex
property to PolygonGraphics
in the time since this was originally asked. It's only valid for "ground primitives", for example polygons that lie directly on terrain and do not have height
or extrudedHeight
properties assigned to them. For those, use my original answer below. But for ground primitives, you can now just assign a zIndex
like this:
var viewer = new Cesium.Viewer('cesiumContainer');
var redPolygon = viewer.entities.add({
name : 'Red polygon',
polygon : {
hierarchy : Cesium.Cartesian3.fromDegreesArray([-115.0, 37.0,
-115.0, 32.0,
-102.0, 31.0,
-102.0, 38.0]),
material : new Cesium.Color(1, 0, 0),
zindex : 1
}
});
var greenPolygon = viewer.entities.add({
name : 'Green polygon',
polygon : {
hierarchy : Cesium.Cartesian3.fromDegreesArray([-118.0, 42.0,
-100.0, 42.0,
-104.0, 32.0]),
material : new Cesium.Color(0, 1, 0),
zIndex : 2
}
});
viewer.zoomTo(viewer.entities);
At the bottom of your question, you mentioned the quick-fix for z-fighting is to simply to turn off the Z buffer for these polygons, by setting some transparency. Transparency happens in an 8-bit Alpha channel, so my favorite value to use is 254.0 / 255.0
, or 0.996
.
But there's another option you'll probably want to turn off, and that's orderIndependentTranslucency
. This is a property of Scene
that can be initialized from an options parameter in Viewer's constructor. When left on, the default for systems that support it, one can always "see" translucent objects behind other translucent objects, regardless of the opacity, and of course the render order doesn't affect the result. But in this case, you want the render order to affect the result, if you want one polygon to obscure the other one.
Here's an example. Click "Run Code Snippet" at the bottom, or paste just the JavaScript section into Sandcastle.
var viewer = new Cesium.Viewer('cesiumContainer', {
navigationInstructionsInitiallyVisible: false, animation: false, timeline: false,
// The next line is the important option for this demo.
// Test how this looks with both "true" and "false" here.
orderIndependentTranslucency: false
});
var redPolygon = viewer.entities.add({
name : 'Red polygon',
polygon : {
hierarchy : Cesium.Cartesian3.fromDegreesArray([-115.0, 37.0,
-115.0, 32.0,
-102.0, 31.0,
-102.0, 38.0]),
// The alpha of 0.996 turns off the Z buffer.
material : new Cesium.Color(1, 0, 0, 0.996)
}
});
var greenPolygon = viewer.entities.add({
name : 'Green polygon',
polygon : {
hierarchy : Cesium.Cartesian3.fromDegreesArray([-118.0, 42.0,
-100.0, 42.0,
-104.0, 32.0]),
// The alpha of 0.996 turns off the Z buffer.
material : new Cesium.Color(0, 1, 0, 0.996)
}
});
viewer.zoomTo(viewer.entities);
html, body, #cesiumContainer {
width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
font-family: sans-serif;
}
<link href="http://cesiumjs.org/releases/1.19/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"/>
<script src="http://cesiumjs.org/releases/1.19/Build/Cesium/Cesium.js">
</script>
<div id="cesiumContainer"></div>
Answer is simple, You can add z-index
in your code.
var viewer = new Cesium.Viewer('cesiumContainer');
var red = Cesium.GeoJsonDataSource.load('map1.geojson', {
fill: new Cesium.Color(1, 0, 0, 1.0),
zIndex: 1
});
var green = Cesium.GeoJsonDataSource.load('map2.geojson', {
fill: new Cesium.Color(0, 1, 0, 1.0),
zIndex: 2
});
viewer.dataSources.add(red);
viewer.dataSources.add(green);
It might be useful for a bit different case: polygons have heights and some of them might be transparent or not , also polygon layers lie on top of each other. For resolving z-fighting in this case the good approach is removing bottom part of polygons with option flag {closeBottom: false}. I have adapted code for this case from above comment:
var viewer = new Cesium.Viewer('cesiumContainer', {
navigationInstructionsInitiallyVisible: false, animation: false, timeline: false,
// The next line is the important option for this demo.
// Test how this looks with both "true" and "false" here.
orderIndependentTranslucency: false
});
var redPolygon = viewer.entities.add({
name : 'Red polygon',
polygon : {
hierarchy : Cesium.Cartesian3.fromDegreesArray([-115.0, 37.0,
-115.0, 32.0,
-102.0, 31.0,
-102.0, 38.0]),
// The alpha of 0.996 turns off the Z buffer.
material : new Cesium.Color(1, 0, 0, 1),
closeBottom: false,
height: 1000,
extrudedHeight: 50100
}
});
var greenPolygon = viewer.entities.add({
name : 'Green polygon',
polygon : {
hierarchy : Cesium.Cartesian3.fromDegreesArray([-118.0, 42.0,
-100.0, 42.0,
-104.0, 32.0]),
// The alpha of 0.996 turns off the Z buffer.
material : new Cesium.Color(0, 1, 0, 0.29),
height: 50100,
extrudedHeight: 95000,
closeBottom: false
}
});
viewer.zoomTo(viewer.entities);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With