CesiumGS / cesium-native

Apache License 2.0
392 stars 202 forks source link

No culling of tiles on the other side of the globe #596

Open pjanetzek opened 1 year ago

pjanetzek commented 1 year ago

Hello I wonder how fog culling should prevent rendering tiles from the other side of the globe - it appears not to work here. From Tileset.cpp:

 // CesiumJS will also fade out the fog based on the camera angle,
  // so when we're looking straight down there's no fog. This is unfortunate
  // because it prevents the fog culling from being used in place of horizon
  // culling. Horizon culling is the only thing in CesiumJS that prevents
  // tiles on the back side of the globe from being rendered.
  // Since we're not actually _rendering_ the fog in cesium-native (that's on
  // the renderer), we don't need to worry about the fog making the globe
  // looked washed out in straight down views. So here we don't fade by
  // angle at all.

Is there a plan to implement horizon culling for cesium-native? The cesium updateView is frozen to zoom out without affecting the current tileset in this screenshot. shot-2023-02-22_11-25-50

kring commented 1 year ago

Hi @pjanetzek, that image is quite surprising; I definitely wouldn't expect those tiles to be selected for rendering. Are you using any non-default TilesetOptions? What tileset is this? (looks like it could be Cesium World Terrain + Bing, but I'm not sure) It's strange that the tiles are of such uniform size as well. Anything else you can tell us about what's going on here? Are you able to reproduce this in Cesium for Unreal or Cesium for Unity?

We're not currently planning to implement CesiumJS's form of horizon culling in cesium-native, because it basically amounts of occluding with the ellipsoid, which is not very accurate because terrain is often significantly above or below the ellipsoid. And because I thought it was unnecessary with the distance (fog) culling!

pjanetzek commented 1 year ago

Thanks - yes it should be the default options, but I've also tried with various changed options. The terrain and Bing tileset is from CesiumIon. I'll have a look whether this issue is reproducable with cesium-unreal, though I'm not familiar with that engine. I think it would help to at least use the frustum far plane to determine visibility with CullingVolume - I have to zoom out quite a bit to have the tiles appear due to hardware frustum clipping

shot-2023-02-22_12-08-27

    Options.maximumScreenSpaceError                     = 16.0;
    Options.maximumSimultaneousTileLoads                = 20;
    Options.maximumSimultaneousSubtreeLoads             = 20;
    Options.loadingDescendantLimit                      = 1;
    Options.enforceCulledScreenSpaceError               = true;
    Options.culledScreenSpaceError                      = 64.0;
    Options.maximumCachedBytes                          = 4 * 1024 * 1024;
    Options.enableFrustumCulling                        = true;
    Options.enableOcclusionCulling                      = true;
    Options.enableFogCulling                            = true;
    Options.preloadAncestors                            = true;
    Options.preloadSiblings                             = false;
    Options.forbidHoles                                 = true;
    Options.renderTilesUnderCamera                      = false;
    Options.contentOptions.enableWaterMask              = true;
    Options.contentOptions.generateMissingNormalsSmooth = true;
kring commented 1 year ago

The only unusual option I see there is forbidHoles, but that shouldn't cause what you're seeing.

I think it would help to at least use the frustum far plane to determine visibility with CullingVolume

Well... maybe. In Cesium for Unity, in particular, we go the other way. We select the tiles we want to be visible, and then we adjust the far plane so that they're actually rendered. We don't need to do this in Cesium for Unreal because Unreal appears to use an infinite (or effectively infinite) far plane.

Basically, the "appropriate" far plane / tile selection distance is a function of the camera height. That's what the "fog" concept achieves, in an admittedly roundabout way. Pushing this onto the application / engine by requiring them to set an appropriate far plane themselves seems like a step back.

But it's certainly a straightforward change to allow this as an option, if it's useful.

I have to zoom out quite a bit to have the tiles appear due to hardware frustum clipping

I'm not quite sure what you mean here. How does zooming out further make the tiles appear if they're being clipped by the far plane? I've probably misunderstood you.

thomaspeer commented 1 year ago

I have to zoom out quite a bit to have the tiles appear due to hardware frustum clipping

Hi. Currently, we adjust our camera's near and far clip planes based on the height. We are using a very naive implementation for now. I assume this is what @pjanetzek was referring to. Correct me if needed.

pjanetzek commented 1 year ago

^ that's corrent. I've added a debug printf to the if (isFogCulled) case and it appears to only be hit when the camera height is < ~555000.0, but still tiles on the other side are considered visible.

shot-2023-02-22_13-07-35

kring commented 1 year ago

Ok, that's very interesting. Let me investigate and get back to you.

kring commented 1 year ago

Ok, I can reproduce this in Cesium for Unity.

image

I guess we haven't noticed it because it mostly affects views that are relatively far from the surface and looking straight-ish down. These tend to be the cheapest views to render, so rendering some extra tiles in these views isn't too painful. In views closer to the surface, the fog is "thicker" so we don't render tiles on the other side of the globe. And for horizon views farther from the surface, view frustum culling is effective.

That's mostly an excuse, though. I'll see what we can do about it.

pjanetzek commented 1 year ago

Thank you :) I recall there are some quite tricky cases to handle from having worked on tile visiblity for a globe renderer with terrain previously. Just an idea that might work for horizon culling: Wouldn't it be a safe upper limit for the horizon plane if the maximum terrain elevation (configurable per celestial body) is added to the camera height above ground? This could also safe some more expensive fog culling computations.

kring commented 1 year ago

Do you mind describing that in more detail? I don't think I quite understand what you're suggesting.

pjanetzek commented 1 year ago

oh ok and I also got it the wrong way round.. the horizon would be further away when terrain can be below see level. Is the question about calculating the horizon circle and using it as a plane for culling?

lighthouse (from https://www.johngiovannis.com/content/distance-horizon - I think we can ignore the light refraction case for now :)

Edit: I will get back to my geometry fundamentals book lighthouse2

kring commented 1 year ago

I don't think it's quite that simple. For example, the mountains I've drawn in on the left are below the horizon plane and further than the surface distance, yet they are visible:

image

And to use equations like this at all, we need a camera height above some spherical surface. Which surface? Perhaps the ellipsoid height at the camera location, plus the planet's minimum terrain height above the ellipsoid (which will usually be negative)? I think that would be conservative enough, but it might be too conservative.

Anyway CesiumJS does something like this, plus the notion of a "horizon occlusion point" for each tile. Described in detail here: https://cesium.com/blog/2013/04/25/horizon-culling/ https://cesium.com/blog/2013/05/09/computing-the-horizon-occlusion-point/

pjanetzek commented 1 year ago

yes, right - thanks for the pointers. I'll think about it more

kring commented 1 year ago

By the way, I'm interested in hearing about what you're building with cesium-native, if you're able to share!

pjanetzek commented 1 year ago

I'll have to check what we can share right now in public