-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixed terrain tile culling problems when under ellipsoid #8397
Conversation
Thanks for the pull request @IanLilleyT!
Reviewers, don't forget to make sure that:
|
@kring if you have any thoughts |
This looks like a good change to me, @IanLilleyT! It should be safe, in the sense that it can only result in fewer tiles being culled. And the ellipsoid adjustment should be small for normal terrains (highly exaggerated ones I'm less sure about), so it shouldn't lead to noticeably more tiles being rendered, either. I guess you probably already realized this, but it's still imperfect even with this change, though. It's still possible for tiles to be improperly culled. Here's a sketch to illustrate the problem: Tile A is entirely above the ellipsoid, so no ellipsoid adjustment will happen. But tiles B, C, and D are below the ellipsoid. The camera is situated such that the ellipsoid is deemed to block the camera's view of tile A, so it gets culled. But in reality, A should be visible. This situation is admittedly a bit contrived, though, and this PR doesn't do anything to make it worse. I also think it'd be quite challenging to address this. It would almost certainly need to be done as part of the terrain processing rather than as a runtime tweak like in this PR. So ! |
Hmm, maybe a hybrid approach. Find the min loaded terrain tile, similar to #8398, and use that. Would have to see what performance is like but it would definitely solve these edge case culling problems. Could even get a speedup when all tiles are above the earth, and use that larger ellipsoid to horizon cull more aggressively. Haven't fully thought it through though. |
Some more thoughts on this The only way to horizon cull 100% correctly is to test each tile against the min tile's ellipsoid (see #8397 (comment)). There a few tricky parts about doing this:
|
b053e7e
to
435bce5
Compare
@lilleyse ready for review I refactored the I also messed around for a while trying to trigger the pathological culling case, but couldn't get it. You would need a distant tile with a very abrupt height change. But the more distant a tile, the more likely it has some lower heights in it. So for now I'm moving forward with the original approach. |
Source/Core/EllipsoidalOccluder.js
Outdated
scratchCameraPositionInScaledSpaceShrunk | ||
); | ||
|
||
var distanceToLimbInScaledSpaceSquaredShrunk = Cartesian3.magnitudeSquared(cameraPositionInScaledSpaceShrunk) - 1.0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks mostly similar to the code in the cameraPosition
setter, aside from the minimumHeight
. Can a shared function be used instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unrolled for performance since it's called once per tile per frame (at least for tiles that are partly under ellipsoid). I added a comment to clarify.
@lilleyse ready for another review. I was going to change the name to |
f027939
to
f8525f7
Compare
Tested a few other sites, this seems to have fixed most of the culling bugs. Thanks @IanLilleyT |
Terrain tiles are culled when the horizon blocks them from view, as explained in blog part 1 and blog part 2. But there's a problem when tiles are under the ellipsoid. The second blog post says:
Unfortunately, there are downsides to a more conservative ellipsoid: It increases the number of false positive draw calls and not all terrain providers have the up-front information of global min/max heights.
Instead, this PR does conservative ellipsoids per-tile. So if the tile's minimum height is below 0, it recomputes the tile's horizon occlusion point relative to a shrunk ellipsoid. This shrunk ellipsoid is shrunk just enough to be below the tile's lowest point, and no lower. During the tile culling pass it tests the tile's shrunk horizon occlusion point relative to its shrunk ellipsoid.
As shown in the picture below, the original horizon occlusion point is considered to be blocked by the horizon under existing code. In this PR, the new horizon occlusion point is relative to the shrunk ellipsoid and so is considered visible. (Side note: the shrunk horizon occlusion point would be in a slightly different position than the original. I forgot to draw it.)
And here's the fix in action in Death Valley:
Before:
After:
Before:
After:
A much better test case is if you manually change the
heightOffset
of a heightmap terrain provider to be -10000.0. This makes all tiles go under the ellipsoid and the culling is seriously broken. These problems are fixed in this PR and the correct number of tiles are rendered when checking the cesium inspector.I'm happy to hear thoughts on this approach and the implementation details. All occurrences of
computeHorizonCullingPoint
have been replaced withcomputeHorizonCullingPointPossiblyUnderEllipsoid
andGlobeSurfaceTileProvider
now callsisScaledSpacePointVisiblePossiblyUnderEllipsoid
. An alternative could be to doif (minimumHeight < 0.0) { computeHorizonCullingPointUnderEllipsoid } else { computeHorizonCullingPoint }
, but this would happen in several areas so I thought it would be better to make thePossibly
version. Also, I considered each tile storing its own shrunkEllipsoidalOccluder
, but thought it wouldn't be worth the memory overhead. However, this would avoid the kind-of-funky changes toEllipsoidalOccluder
. Besides the API changes there's also a small runtime cost with this new approach: each tile that is under the ellipsoid has to recalculate the camera position in scaled space every frame. It's not especially heavy math so I'm not too concerned.So let me know what you think! I'll add tests once the design is more finalized.