OpenGeoscience / geojs

High-performance visualization and interactive data exploration of scientific and geospatial location aware datasets
https://opengeoscience.github.io/geojs
Apache License 2.0
438 stars 75 forks source link

Share webGL contexts between layers #942

Closed manthey closed 5 years ago

manthey commented 6 years ago

Currently, having more than 15 webgl layers will exhaust the available webgl contexts. If webgl layers do not have non webgl layers between them by z-index, a single context can be used instead. This should be done automatically. When there are multiple layers, the webgl renderer will need to apply opacity for each layer, rather than using the opacity on the div.

manthey commented 5 years ago

Regarding shared webgl contexts, layering, and opacity.

When two layers share a webgl context, I intend that they will also share a depth buffer. This will be a difference between separate contexts and shared contexts (but, when we support full 3D, I view this as a positive feature).

On tile layers, we render different levels of tiles at slightly different z values, all "just behind" their actual z value. When we share contexts, multiple tile layers will composite as expected (with layers with higher layer z-indices just above those with lower). If the shared context has both tile and feature layers, then features with the same z value as tiles will always appear above the tiles, even if the tile layer's z-index is above the feature layer's z-index. To do otherwise, we could either avoid sharing contexts between tile and feature layers OR there will need to be slight z offsets for all layers (not just tile layers) to force them to composite properly. I think that, for now, we just accept that when tile and feature layers share context, tiles are behind features with the same z value regardless of layer z-index.

Sharing context between layers with different opacities is tricky. The results of changing feature opacity instead of layer opacity is not the same (for instance, a layer with 100% opacity and overlapping lines each with 50% opacity will form an area with 75% opacity, whereas a layer with 50% opacity and overlapping lines with 100% opacity will have everything at 50% opacity). Either we will have to render each layer into a frame buffer object or not share contexts between layers with different opacities.

For automatic merging of shared webgl contexts, I think the simplest approach would be to only share contexts between adjacent webgl layers that have the same opacity (and layers with 0 opacity or 0 visibility could be shared, too, as they will skip rendering).

Feedback welcome, as I am about to add code for automatic sharing of webgl context between adjacent webgl layers.

matthewma7 commented 5 years ago

Hi @manthey, this all sounds reasonable to me. Are you thinking about providing an option to enable context reuse or always reuse? Just asking, I know it could be a lot more work to make it optional.

manthey commented 5 years ago

I am thinking that context sharing would be optional.

Currently, you can either create a layer and have it create a renderer instance or you create the layer while specifying an existing renderer instance. In the second case, layers share the context. This works correctly on my development branch except for honoring opacity and visibility properly.

I am thinking that if you create a layer without passing an existing renderer instance and a flag (canShareContext?) were set, that renderer instances would be shared where possible. I think that this would be the default, so you would have to explicitly clear this flag to avoid auto-sharing contexts.

As I mentioned above, I think contexts would only be shared if the opacity were the same value. This means that if you have three layers A B C that are using one context and adjust the opacity of layer B, you would end up with three separate contexts. I think this is simpler than implementing frame buffer objects, but could be confusing if someone is using the shared contexts to use a single z-buffer for 3D purposes.

matthewma7 commented 5 years ago

Got it, thanks for the answering. 🙂

manthey commented 5 years ago

I've got a local branch where this all works, but it requires a minor update to the vgl package: https://github.com/OpenGeoscience/vgl/pull/106. Once that gets merged and a new vgl release made, I'll make a PR to finish this.

manthey commented 5 years ago

Resolved in #975.