Skip to content
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

Support abritrary expression functions #28

Closed
lucaswoj opened this issue Oct 7, 2016 · 5 comments
Closed

Support abritrary expression functions #28

lucaswoj opened this issue Oct 7, 2016 · 5 comments

Comments

@lucaswoj
Copy link

lucaswoj commented Oct 7, 2016

The proliferation of function types and desire for more advanced function features keeps bringing me back to the idea of supporting arbitrary expression function types

population / area ^ 2 + 7

This is doable so long as we create a syntax that is:

  • easily evaluated in GL JS
  • easily evaluated in GL Native
  • compilable to GLSL 😬
  • a valid subset of an existing programming language
@jfirebaugh
Copy link
Contributor

jfirebaugh commented Oct 10, 2016

(I talked with @ansis about this a few weeks ago. Let's see if I can accurately capture the conclusions here.)

Arbitrary expressions should be possible, and not pose too much of an issue implementation-wise, if they satisfy the following constraints:

  • The property-dependent and zoom-dependent portions of the expression are separable.
  • The property-dependent portion is evaluable to a single scalar numeric or numeric vector value.
  • The zoom-dependent portion remains a simple linear interpolation (not a free-form expression).

These constraints allow us to continue using the same basic implementation strategy as we currently do:

  • Evaluate the property-dependent portion at layout time, on CPU, and the zoom-dependent portion at paint time, on GPU.
  • Don't require a compiling an individual GLSL program for every layer; keep the number of unique shaders to (at most) each unique combination of "property X is/is not data-driven" bits.

@anandthakker
Copy link

anandthakker commented Nov 29, 2016

Couple thoughts:

  1. What is the advantage of evaluating the "property-dependent portion" at layout time? Assuming it were feasible to generate the appropriate GLSL code such that the whole DDS function could be evaluated in the shader, what would be the downside? (I'm about one tutorial deep in learning about GLSL, so this may be an absurd question)

  2. The property-dependent and zoom-dependent portions of the expression are separable.
    The property-dependent portion is evaluable to a single scalar numeric or numeric vector value.
    The zoom-dependent portion remains a simple linear interpolation (not a free-form expression).

@jfirebaugh I am not sure exactly what these requirements entail. Do they mean that expressions would have to be reducible to the form F(properties) * z + G(properties)? If so, why? It seems to me that we could allow any arbitrary expression H(properties, zoom), and then for each feature, the partial evaluation H({ ... }, zoom) gives us an expression depending on zoom only. Even if the zoom-only expression is not linear, couldn't it still be interpolated linearly?

  1. Separately, here's a probably-dumb idea: rather than generalizing style functions with arbitrary expressions, we could instead add a concept of derived/computed properties on the source (maybe by way of a custom source, or maybe just an enhancement to core vector/geojson sources). E.g.:
{
  type: vector,
  url: '...',
  'computed-properties': [
    { name: 'pop-density', value: 'pop10 / area' }, // assuming pop10 and area are existing properties
    { name: 'pop-sqrt', value: 'Math.sqrt(pop10)' },
    { name: 'pop-density-scaled', value: 'pop-density / 100' } // computed prop using previous computed prop
  ]
}

This would mean that style functions could remain as they are. In some cases this would be less ergonomic than having the expression syntax be part of the DDS function, since it would mean authoring the math in one place (source) and the stops in another (style layer). On the other hand, it might also prove to be a meaningful and useful separation -- especially in cases where multiple style layers need to use the same derived property.

@jfirebaugh
Copy link
Contributor

@anandthakker The main reasons are the two I listed:

  • Evaluate the property-dependent portion at layout time, on CPU, and the zoom-dependent portion at paint time, on GPU.
  • Don't require a compiling an individual GLSL program for every layer; keep the number of unique shaders to (at most) each unique combination of "property X is/is not data-driven" bits.

We want to avoid unique programs for every layer because compilation and switching programs are the two most expensive operations in GL.

Other reasons we don't want to evaluate the property portion of the function in the shader:

  • It would require a separate program attribute for each property used in the function (versus a single attribute per data-driven paint property in the current implementation)
  • It would involve more computation at render time, reducing the frame rate. We want to compute as little as possible on a per-frame basis.
  • It's not clear how we would support categorical functions and string-valued feature properties.

Computed properties sound like a good idea. But I don't think we'd want to use a string-embedded syntax for them, but rather whatever "arbitrary expression function" syntax we develop here (or in mapbox/mapbox-gl-style-spec#104). So I see them more of an extension of this issue than a replacement.

@lucaswoj
Copy link
Author

lucaswoj commented Dec 2, 2016

We want to avoid unique programs for every layer because compilation and switching programs are the two most expensive operations in GL.

I wonder if there would be an appreciable performance penalty if we

  • keep the number of unique shaders to (at most) each unique combination of "property X is/is not data-driven" bits
  • compile complete expressions to GLSL
  • put multiple expressions into a single single shader
  • pass layer id as a uniform to the shader to select the proper expression using an if / else if block
    • conditionals based on uniforms aren't too 😈 in shaders

@lucaswoj
Copy link
Author

👉 mapbox/mapbox-gl-style-spec#630

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants