-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Enable property functions for {text,icon}-{color,halo-color} #4186
Conversation
Nice! We implemented this earlier this week in our fork (for sdf icons). Just a thought going through the Symbol Bucket code: Would it make sense to split up text (glyph) and icon rendering completely? The bucket code contains a lot of |
This is working for the simple Also, the existing approach to |
@Scarysize good question! I'm 💯 with you on those crazy long parameter lists. I definitely think this part of the codebase could use a solid refactor, and splitting up text/icon might be a good route to take.... I'm personally not very familiar w/ the history of the symbol stuff, though, so there might be lurking subtleties that I'm not aware of. |
The simplest design I can think of is adding a new parameter to This method is responsible for setting up the connections between shader attributes and struct array members. By default there is a 1:1 mapping of shader attributes to struct array members. We could solve this problem by making that relationship a little looser, allowing callers of segment.vaos[layer.id].bind(gl, program, buffers.layoutVertexBuffer, buffers.elementBuffer, null, segment.vertexOffset, {
attributeAliases: {
'color': 'halo-color'
}
}); Happy to voice on this if you have any follow-up questions. 😄 |
Other options:
|
Update: ruled out consolidating the halo and fill in a single call (see #596 ). Because @jfirebaugh indicated in chat that the attributeAliases approach would likely be difficult to carry over to |
a8791b2
to
61d8a16
Compare
|
js/data/bucket/symbol_bucket.js
Outdated
@@ -358,7 +366,7 @@ class SymbolBucket { | |||
// the buffers for both tiles and clipped to tile boundaries at draw time. | |||
const addToBuffers = inside || mayOverlap; | |||
this.addSymbolInstance(anchor, line, shapedTextOrientations, shapedIcon, this.layers[0], | |||
addToBuffers, this.symbolInstancesArray.length, this.collisionBoxArray, feature.index, feature.sourceLayerIndex, this.index, |
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.
Per conversation w @mollymerp, I replaced the (unused) index
field with a featureIndex
, which provides a mapping back to from the symbol instance to the feature it came from. This allows us to retrieve the feature's properties down in place()
.
This will likely need a bit of reworking when we return to the cross-source symbol placement quest, but since we don't know exactly what that'll look like, I think we should cross that bridge when we come to it.
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.
Any context on how the index
field became unused?
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.
@lucaswoj I believe it never was used, but rather was there on the hypothesis that it might be needed during cross-source placement. @mollymerp does that sound right to you?
@jfirebaugh @lucaswoj k -- this is still a subset of the symbol paint properties (list is here #2730 ), but it'd be good to go ahead and get some 👀 on it, esp. since this is my first foray into this area of the codebase. |
shaders/symbol_sdf.fragment.glsl
Outdated
lowp float dist = texture2D(u_texture, v_tex).a; | ||
lowp float fade_alpha = texture2D(u_fadetexture, v_fade_tex).a; | ||
lowp float gamma = u_gamma * v_gamma_scale; | ||
lowp float alpha = smoothstep(u_buffer - gamma, u_buffer + gamma, dist) * fade_alpha; | ||
|
||
gl_FragColor = u_color * (alpha * u_opacity); | ||
gl_FragColor = color_to_use * (alpha * u_opacity); |
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.
Instead of color
, halo_color
, and color_to_use
how about fill_color
, halo_color
, and color
?
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.
Yeah. I'd foolishly assumed I needed to stick with the attribute-name <=> paint-property-name-sans-layer-type-prefix mapping, but doing #4186 (review) will free us up to improve the naming here.
js/data/program_configuration.js
Outdated
@@ -210,7 +210,8 @@ function getPaintAttributeValue(attribute, layer, globalProperties, featurePrope | |||
} | |||
|
|||
function normalizePaintAttribute(attribute, layer) { | |||
const name = attribute.property.replace(`${layer.type}-`, '').replace(/-/g, '_'); | |||
const layerTypePrefix = layer.type === 'symbol' ? /text-|icon-/ : `${layer.type}-`; | |||
const name = attribute.property.replace(layerTypePrefix, '').replace(/-/g, '_'); |
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.
Can you think of any cases where this magic behaviour might bite us later? I'd be interested to see if there was a way to specify this behaviour explicitly within SymbolBucket
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.
Can you think of any cases where this magic behaviour might bite us later?
@lucaswoj not offhand, but I'm 💯 with you in being uneasy / less than satisfied with this magic.
I'd be interested to see if there was a way to specify this behaviour explicitly within SymbolBucket instead.
👍 I'm thinking we can allow the bucket to explicitly define attribute.name
, and then have normalizePaintAttribute
just use that if it's there, instead of computing the attribute name from the paint property name.
@lucaswoj addressed your points re: bad magic and naming by explicitly setting the attribute names in When |
js/data/bucket/symbol_bucket.js
Outdated
@@ -184,6 +192,12 @@ class SymbolBucket { | |||
// It's better to place labels on one long line than on many short segments. | |||
this.features = mergeLines(this.features); | |||
} | |||
|
|||
// set up this mapping to allow for constant-time lookups in place() | |||
this.featuresByIndex = {}; |
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.
Rather than create a separate index, can we attach a reference to the feature properties to the symbolInstance
?
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.
@jfirebaugh the symbolInstance is being stored (at populate()
time) in a StructArray (this.symbolInstancesArray
), so we can't attach a reference.
Granted, (a) we're not yet using symbolInstancesArray
on a different thread, and (b) once we do (for cross-source placement), we'll have to find a different way to handle the paint attributes, since presumably whichever thread gets the array won't have the property data from the source.
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.
Let's adjust/replace symbolInstancesArray
based on the requirements here for data-driven properties. We can revisit its use in cross-source symbol placement when we're ready to work on that feature again.
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.
Sure; if we're doing that I'd say we should go with 'replace' over 'adjust': adjusting it to these requirements would mean changing it from a StructArray, thus making it non-transferrable and no longer suitable for the cross-source placement project... if that's going to be the case, I don't see much reason to hold on to this state (symbolInstancesArray
, symbolQuadsArray
) at the WorkerTile level.
I'm good to go ahead with this, but I just want to flag that dropping symbolInstancesArray will make the changes in this PR a notch more invasive, removing some stuff that we may end up having to partially redo later when we tackle cross-source placement -- but it's probably true that even if we left it in place, making it work with data-driven styling would anyway have caused significant changes to what's there now.
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.
The prep work for this is done in #4217. Tomorrow AM I'll rebase on that, which will allow us to just place a direct reference to featureProperties
onto each symbolInstance
as you suggested.
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.
I'm happy with this! Deferring to @jfirebaugh for the final 👍
52653a5
to
c7fef40
Compare
@lucaswoj @jfirebaugh rebased onto the refactor in #4217, so that one should get merged first, but after that's in I think this is ready. Compare this PR's changes only at refactor-symbol-instances...dds-symbol-paint |
c20020e
to
b579604
Compare
* Enable property functions for {text,icon}-color * Update expected images for {icon,text}-color render tests * Add render tests for {icon,text}-halo-color property functions * Drop unneeded feature map
Adds property function support for:
Refs #2730
Checklist