CesiumGS / cesium-native

Apache License 2.0
414 stars 210 forks source link

Multi view rendering #928

Open Lee-Bull opened 1 month ago

Lee-Bull commented 1 month ago

Hi, I'm using Cesium Native for a project and wondered if you could clarify some issues I'm considering with the API.

My software requires multi viewport rendering, with all views sequentially, progressively read and rendered over a short period of time until they all converge at the required LODs. Usually what happens in engines of this type is that multiple queries of various types, including for rendering, are created and synchronously or asynchronously executed with data fetched in the backgrounds thread(s) with LOD control and fetch ordering considering all query requirements and prioritizations.

Cesium3DTilesSelection::Tileset::updateView() would appear to provide a feature for multiple view rendering, given that it receives a vector of ViewState frustums. However, given that it returns a single ViewUpdateResult with a single tilesToRenderThisFrame tile list, it doesn't seem obvious how the tiles appropriate to each frustum would be obtained, or sorted out of that list.

Alternatively, if it's feasible to only provide a single ViewState to multiple calls to updateView() for each view, that would be doable, but looking at the object lifetime for returned Tiles purging between calls (and that they're not on smart pointers) it would suggest that's not necessarily an intended approach. The internals of updateView() would need to be able to handle this kind of thrashing around between views too.

I guess it's possible to have an entire Tileset pipeline per view, but that seems wasteful and would need to rely on caching to share data between instances for some period.

Would you please be able to shed some light on this one?

Kind Regards, Lee.

kring commented 1 month ago

Hi @Lee-Bull,

The intention is that you call updateView with the multiple views. Then, render all of the tilesToRenderThisFrame for every view. You may be able to skip some of the tiles in some of the views by doing extra frustum or occlusion checks. In Unreal and Unity, for example, these visibility checks are automatically done by the engine.

It's conceptually possible to build up an optimal set of tiles for each view, but that's not currently implemented. It would inherently require loading more tiles (because tiles covering the same area at multiple LODs would be required, whereas the current approach only covers any given part of the globe with one LOD), though it might lighten the rendering load.

Lee-Bull commented 1 month ago

Hi Kevin,

Thanks very much for your swift reply. It would be preferable to have individual updateView queries called on each View at different times, asynchronously returning data currently available (or waiting to complete), with results that use smart pointers to required Tiles for the view so the result object lifetime remains as required for processing.

I can see some benefit of taking the union of all LOD requirements for the views. I can see issues with it too, for example the rendering performance drop as it's not really per view LOD control, also maybe some aliasing. Also popping/hysteresis if one view A of a region requires a high LOD, forcing view B to use the high LOD, but view A then moves away and the LOD drops suddenly in B.

You're right in saying dealing with each view individually would require more tile reads, at least for replacement hierarchies.

If we use the current approach, it means we need to cull working set leaf tiles to views in linear time. Presumably culling has already been done internally during the update traversal, so it's a shame we can't leverage that.

I'll have a think. We'll either think of a way of using Cesium Native's updateView approach or develop custom traversal code that's closer to our needs, though ideally we'd rather keep as closely in sync with the Native API as possible.

Thanks very much for your time, Lee.

kring commented 1 month ago

Yeah I don't disagree with anything you've written. It would be possible and useful to extend cesium-native to support proper per-viewport tile selection, but it will take some work.

Lee-Bull commented 1 month ago

Thanks, still thinking this one over, it's tough to shoehorn it into our current engine framework which requires separate, iterative queries performed at any time. It's still 50/50 whether I use Native's updateView() or write something custom. Contributing to the Cesium code base might be possible but require more knowledge of it than I have at the moment.