mapbox / mapbox-gl-style-spec

76 stars 38 forks source link

Add "cover" layer type #626

Closed jfirebaugh closed 7 years ago

jfirebaugh commented 7 years ago

Add a new layer type: cover.

This layer requires a source property, and prohibits the source-layer and filter properties. It has the paint properties cover-color, cover-pattern, cover-opacity, which behave the same as the equivalent background layer properties. In addition, it has a cover-type paint property, which is an enumeration with the following values:

The cover-type paint property does not support property or zoom-and-property functions.


This proposal aims to satisfy two distinct use cases.

Use case: show a pattern or color in lieu of a loading or errored raster tile (https://github.com/mapbox/mapbox-gl-js/pull/3694). When raster tiles use fully transparent pixels to represent "no data", it is difficult or impossible to distinguish between an area fully without data, an area in which a tile or tiles have yet to be loaded, and an area in which tiles have failed to load due to network or other errors. The cover layer type provides a means to do so. To distinguish areas that have yet to be loaded, one can add a cover layer at the desired z-index with cover-type: "tile-loading". Likewise cover-type: "tile-failed" to distinguish areas where tiles have failed to load.

Use case: allow a platform- or application-defined "matte" color or pattern to show through areas of the map where no tile data has been loaded (https://github.com/mapbox/mapbox-gl-native/issues/119). For example:

image

A background layer does not suffice for this use case for two reasons:

However, the combination of a platform- or application-defined background rendering step, plus cover layer does suffice:


Implementation notes and future directions.

Implementing a cover layer type provides us with a pathway, in a future revision of the specification, to replace the background layer type with a single set of top-level style properties nested under a background key (in the style of light). The background then would then be defined statically, with multiple instances, or interleaving with other layers, being prohibited.

This would simplify the rendering implementations, which currently rely on analysis of all style layers to determine if the background can be rendered with a simple glClear operation or not.

This would also lead to better clarity in naming (https://github.com/mapbox/mapbox-gl-style-spec/issues/219): "background" would refer to a portion of the rendering that is truly in the background, behind all layers, and "cover" to layers which can be arbitrarily z-ordered but do behave relative to layers underneath them as their name suggests.

It would also provide a clearer path to adding rendering support for a sky color distinct from the ground (https://github.com/mapbox/mapbox-gl-native/issues/2190).

1ec5 commented 7 years ago

This layer requires a source property, and prohibits the source-layer and filter properties.

This maps cleanly to what the iOS and macOS SDKs are calling a “foreground style layer”, as opposed to the background style layer type we’re trying to phase out. (It isn’t much of a problem that cover layers would provide a background in the artistic sense; we can always massage the class hierarchy in the future.)

lucaswoj commented 7 years ago

It is desirable to continue having our layer types correspond with drawing primitives as they are implemented by most graphics editing software (fill, polygon, line, ...). This correspondence is possible if we reframe "covering a source" as a behaviour that can be applied to a fill layer rather than a layer type itself.

In practice, this could look like making the cover-type property available to the fill layer (with a some renaming, thanks for the ideas @1ec5 https://github.com/mapbox/mapbox-gl-style-spec/issues/624#issuecomment-268287440).

{
    "type": "fill",
    "tile-filter": "loading",
    "tile-filter-source": "mapbox"
    ....
}

Points of Discussion

jfirebaugh commented 7 years ago

@lucaswoj I'm not 100% sure I understand what you're proposing. Is it like:

I think that behavior would make the rendering model more confusing, because it would mean that fill layers have two drastically different behaviors depending on the presence or absence of tile-filter.

Would it make sense to expose this feature on raster sources too?

Raster sources are one of the two primary use case for this feature, so... yes? This answer seems obvious, so I feel like I must be misunderstanding what you're getting at here.

lucaswoj commented 7 years ago

Eek. A few things I said in there were confusing / wrong. Let me try to clarify:


I was thinking so much about the background -> fill / fill -> polygon mapping that I wrote this comment as if that had already happened. What I intended is better specified by

{
    "type": "background",
    "tile-filter": "loading",
    "tile-filter-source": "mapbox"
    ....
}

Raster sources are one of the two primary use case for this feature, so... yes? This answer seems obvious, so I feel like I must be misunderstanding what you're getting at here.

Here I was thinking about exposing tile-filter on raster layers. For example, on the satellite / hybrid style, we might choose to hide the satellite raster layer until the vector features had loaded.

We don't need to implement this immediately. I brought it up as an example of the benefits of thinking about tile-filter as a composable behaviour rather than a layer type.

lucaswoj commented 7 years ago

This issue was moved to mapbox/mapbox-gl-js#4156