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.19k stars 3.36k forks source link

z-fighting caused by overlapping polygons #1456

Closed aramk closed 10 years ago

aramk commented 10 years ago

I've been experiencing z-fighting:

z-fighting

I've been trying to resolve the issue like so:

var scene = this._widget.scene;
scene.farToNearRatio = 4; // Changed from 1000

This increases the number of frustums by a lot and this helps a bit, but doesn't eliminate the issue. It also results in less performance. Is there an easy solution to this that I'm missing? I've read up on other issues and pull requests, and even this presentation which helped understand the concepts.

My next attempt will be to create z offsets for the polygons and attempt to prevent them overlapping. This is somewhat naive though, so let me know if there's a better way :smiley:

mramato commented 10 years ago

One option could be to give the polygons an imperceptable alpha value, like 0.999 instead of 1.0. Here's a simple Sandcastle example that does just that based on the layer primitives picking example

require(['Cesium'], function(Cesium) {
    "use strict";

    var handler;

    function addOverlappingPolygons(scene, ellipsoid) {
        var primitives = scene.getPrimitives();

        // Add primitives from bottom to top.
        var redPolygon = primitives.add(new Cesium.Polygon({
            positions : ellipsoid.cartographicArrayToCartesianArray([
                Cesium.Cartographic.fromDegrees(-70.0, 30.0),
                Cesium.Cartographic.fromDegrees(-60.0, 30.0),
                Cesium.Cartographic.fromDegrees(-60.0, 40.0),
                Cesium.Cartographic.fromDegrees(-70.0, 40.0)
            ])
        }));
        redPolygon.material.uniforms.color = new Cesium.Color(1.0, 0.0, 0.0, 0.999);

        var bluePolygon = primitives.add(new Cesium.Polygon({
            positions : ellipsoid.cartographicArrayToCartesianArray([
                Cesium.Cartographic.fromDegrees(-75.0, 34.0),
                Cesium.Cartographic.fromDegrees(-63.0, 34.0),
                Cesium.Cartographic.fromDegrees(-63.0, 40.0),
                Cesium.Cartographic.fromDegrees(-75.0, 40.0)
            ])
        }));
        bluePolygon.material.uniforms.color = new Cesium.Color(0.0, 0.0, 1.0, 0.999);

        var greenPolygon = primitives.add(new Cesium.Polygon({
            positions : ellipsoid.cartographicArrayToCartesianArray([
                Cesium.Cartographic.fromDegrees(-67.0, 36.0),
                Cesium.Cartographic.fromDegrees(-55.0, 36.0),
                Cesium.Cartographic.fromDegrees(-55.0, 30.0),
                Cesium.Cartographic.fromDegrees(-67.0, 30.0)
            ])
        }));
        greenPolygon.material.uniforms.color = new Cesium.Color(0.0, 1.0, 0.0, 0.999);

        // Give polygons identifiers for easy lookup later
        redPolygon.id = 0;
        bluePolygon.id = 1;
        greenPolygon.id = 2;

        // simple flags used for multi-picking
        redPolygon.picked = false;
        bluePolygon.picked = false;
        greenPolygon.picked = false;
    }

    function layerCompositePrimitive(scene, ellipsoid) {
        Sandcastle.declare(layerCompositePrimitive);    // For highlighting in Sandcastle.
        addOverlappingPolygons(scene, ellipsoid);

        var primitives = scene.getPrimitives();
        // Move the primitive that the mouse is over to the top.
        handler = new Cesium.ScreenSpaceEventHandler(scene.getCanvas());
            handler.setInputAction(function(movement) {
                var p = scene.pick(movement.endPosition);
                if (Cesium.defined(p) && primitives.contains(p.primitive)) {
                    primitives.raiseToTop(p.primitive);
                }
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    }

    var widget = new Cesium.CesiumWidget('cesiumContainer');

    var ellipsoid = widget.centralBody.getEllipsoid();
    var scene = widget.scene;

    layerCompositePrimitive(scene, ellipsoid);
    Sandcastle.highlight(layerCompositePrimitive);

    Sandcastle.finishedLoading();
});

and a screenshot

image

Of course this is not my area of expertise. @pjcozzi and @bagnell what is our official recommendation here?

aramk commented 10 years ago

Thanks for that @mramato. I tried it out and I got this:

It seems that it overlays any extrusions and those extrusions appear hollow. I think @pjcozzi has mentioned that this is a known issue. For flat surfaces only however, this is a great fix.

pjcozzi commented 10 years ago

My next attempt will be to create z offsets for the polygons and attempt to prevent them overlapping.

For this case, that is the right approach.

aramk commented 10 years ago

Cheers for that, I'll post my design here shortly.

aramk commented 10 years ago

Yep, that worked for me. Feel free to close the issue if this is the recommended method to deal with z-fighting. Thanks!

To elaborate, I had a tree of entities - some extruded polygons and some flat polygons, and I used the depth of the item in the tree as an absolute z-index multiplied by a small offset of 0.1 metres when setting the elevation for the polygon.

pjcozzi commented 10 years ago

Glad it worked out.

By the way, if you are making an app that would be appropriate to showcase on the cesium website (like these), email me (pjcozzi@gmail.com), and we'll help get it up.

aramk commented 10 years ago

Thanks, we are indeed! We're in the process of building an abstracted JavaScript globe visualisation library for our systems and the main implementation is in Cesium. We're looking forward to releasing it as open source and look forward to working alongside other Cesium developers at improving the library in the future.

pjcozzi commented 10 years ago

Great - we look forward to your progress.

pjcozzi commented 7 years ago

@meenalpatil-2007 have you tried posting your question on the Cesium forum? It will get more attention there, especially since this issue is closed. Also, include an animation if possible to help diagnose. A workaround may be to make the yellow mesh slightly smaller.

meenalpatil-2007 commented 7 years ago

@pjcozzi, I have already posted a question in cesium forum But no satisfying answer I got there. Could you please post answer there as you say this is closed issue?

Thanks :)

cguldner commented 6 years ago

@mramato The sandcastle link doesn't have the .999 in there anymore, and if you do try to add it, you get a lot of intersecting parts of the polygons. Is there another way to fix this?

hpinkos commented 6 years ago

Hello @burn123, you can disable order independent translucency by passing that option into the viewer:

var viewer = new Cesium.Viewer('cesiumContainer', {
    selectionIndicator : false,
    orderIndependentTranslucency: false,
    infoBox : false
}); 

That should make the polygons layer the way you want.

In the future, you should ask question like this on the forum. We use GitHub for tracking bugs and planning new features. And since this issue is closed, I almost didn't see your question.