tangram-es icon indicating copy to clipboard operation
tangram-es copied to clipboard

Support custom attributes in style configuration

Open matteblair opened this issue 4 years ago • 2 comments

In a style declaration, the shaders block can now contain a new entry called attributes - a mapping of names to properties of custom vertex attributes. Those new attributes are given values in draw groups by assigning a value to the attribute's name in a new attributes block. All together, the new syntax looks like this:

buildings:
  base: polygons
  shaders:
    attributes:
      height:
        type: float
    blocks:
      color: |
        // Use the custom attribute's varying to shade by height
        color.rgb = vec3(min(height / 100., 1.), 0., 0.);
  draw:
    # use default draw parameters to set the height attribute value from the height feature property
    attributes:
      height: function() { return feature.height; }

The feature is fully described in the Tangram JS PR: https://github.com/tangrams/tangram/pull/739

matteblair avatar Dec 31 '19 05:12 matteblair

For the first implementation of this, I'm thinking we'll create a separate vertex buffer for these custom float values and "point" the attributes at those (i.e. we'll access them in a non-interleaved way). This is mostly because it's very convenient to interact with our "base" vertex layouts as C structs and we've put a lot of care into making them compact and nicely laid-out. Using non-interleaved attributes is probably going to negatively impact performance to some degree - worth measuring when we get it working.

...

More thoughts after planning an implementation for this:

For any custom attribute data larger than a single float, it will be much more efficient to give each vertex an index into a collection of data rather than embed the data in the vertex itself.

The thing about attributes is that they have to be duplicated for every vertex. But for any given feature, we only assign one value to the attribute. That means for polygon and polyline features we're duplicating every attribute value at least three times, often more than that, and sometimes hundreds of times!

Instead of duplicating the attribute values in-place, we could create a GPU buffer of all the distinct values and give each vertex an index into this buffer to perform a lookup in the shader. This index would probably be 32 bits, so if we're only looking up another 32-bit float then we save nothing (in fact we use more space). But if we're looking up several floats, a vec4, or a mat4x4, then we'll be using only a fraction of the vertex bandwidth!

matteblair avatar Dec 31 '19 05:12 matteblair

Once available, I'll use this immediately to replace several ugly hacks that I'm currently using!

warpedgeoid avatar Apr 07 '20 03:04 warpedgeoid