-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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 for "dashed" polylines #5159
Conversation
This is awesome @jasonbeverage, thanks! This has been a frequently requested feature and will make the Cesium community very happy 😄 |
Fixes #2584 |
Thanks @jasonbeverage. This is a pleasant surprise and will be a very popular feature! I would like to review this before the final merge. @bagnell should also take a look at this first since he wrote the original polyline shader, but he's busy for probably all of this week. In the meantime, if anyone has cycles to review or even just test this, please jump in! @jasonbeverage I'm not sure if you've already read it, but you might like this paper: Shader-Based Antialiased, Dashed, Stroked Polylines |
Awesome work @jasonbeverage. You keep cranking out some great stuff. I'm not qualified to review the shaders here, but the Entity and CZML pieces look spot on (will look closer as soon as I have time if no one else beats me to it). One of the things me and @bagnell have talked about for stippled lines is the ability to specify a custom pattern (perhaps through a string like |
This is crazy awesome. @mramato You probably know shaders can't directly take a string, but we could pass a float parameter to indicate a percentage of dash vs. gap, or I could even imagine passing a one-dimensional alpha map that supplies a dashing pattern to use. That would be for a future version of course, this seems cool enough as-is that it should probably go in without a lot of feature creep. Also I was thinking it could be useful to supply a second color for use in the gaps, instead of just discarding them (for example, use the same color with less alpha, or alternate the brightness, etc). But again, that's feature creep, and this is plenty good enough already. Dashed lines (as they are now) will be very useful in combination with the depthFail feature going on in #5160. Underground lines are crying out for dashes. |
Don't merge this just yet, I'm going to try to push a couple more things and see what you think. |
@jasonbeverage great. If you're making changes can you switch |
Sure thing, just pushed that change. |
I got asked by @GatorScott to test with a more curved path, and I had an inclined GEO handy. Here's a gist. It works pretty well, even for this tough case. |
I just pushed a few changes. There is a new dashPattern property for the PolylineDashMaterial that defines a 16 bit stipple pattern. I changed some of the defaults so that dashLength is 16 pixels so it lines up per pixel (approximately) with the dash pattern. The default dash pattern is 255 (0000 0000 1111 1111). I've also added a new Polyline Dash sandcastle example. Also, just wanted to say thanks to @timoore for doing the initial work on this effort, including the dashPattern logic. Our original approach just used the distance along the line to drop pixels, but that caused too many artifacts with your wide polyine algorithm (similar to what you'd see with the StipeMaterial with the direction set to vertical). I came up with the screen space fragment shader based stippling just recently and the artifacts aren't nearly as bad. |
} | ||
result.color = Property.getValueOrClonedDefault(this._color, time, defaultColor, result.color); | ||
result.dashLength = Property.getValueOrDefault(this._dashLength, time, defaultDashLength, result.dashLength); | ||
result.dashPattern = Property.getValueOrDefault(this._dashPattern, time, defaultDashPattern, result._dashPattern); |
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 don't think result._dashPattern
gets an underscore here.
* @param {Object} [options] Object with the following properties: | ||
* @param {Property} [options.color=Color.WHITE] A Property specifying the {@link Color} of the line. | ||
* @param {Property} [options.dashLength=16.0] A numeric Property specifying the length of the dash pattern in pixel.s | ||
* @param {Property} [options.dashPattern=255.0.0] A numeric Property specifying a 16 bit pattern for the dash |
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.
Typo
I wonder if CZML (and maybe Entity) can take a 16-character string instead of numeric
Could this be converted to 255 by testing each char position and setting a bit? This would make the pattern more user-friendly. |
Here's some code to turn an arbitrary-length string of spaces and dashes into a closest-approximation 16-bit field. This just iterates the 16 bits, picks the closest char based on length of input string, and figures out if it will set that bit or not.
|
Just pushed a fix for my fat finger typos :) |
I like the dash string idea. Would PolylineDashMaterialProperty.getValue just need to call that to get the appropriate float value to feed the uniform? |
Off the top of my head I'm not sure where it goes. I'd have to research a bit. Curious to hear @mramato's thoughts before we go too far on it. |
I've just been mashing 0 and 1 into the Windows programmer calculator and copying the resulting decimal value :) I also just tried your gist and it looks awesome! |
Thanks again to both of you! |
I only have that one comment. Looks good! Thanks @jasonbeverage! I believe @lilleyse also wants to review this. |
@jasonbeverage I spent some time playing with your branch and the PolylineDashMaterial shader today. I created a branch (dashedlines-2) that has your changes plus some of my own. It adds a length in meters from the first point on the line as a new vertex attribute and I tried to compute I still want to see this PR merged into master. Computing the dashes based on line length can sit in a branch until someone has time to work on it. |
* @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise. | ||
*/ | ||
PolylineDashMaterialProperty.prototype.equals = function(other) { | ||
return this === other || // |
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.
Is the trailing //
here and below required?
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.
Hey @pjcozzi it's not necessary and I've just pushed a change removing it.
Source/Shaders/PolylineCommon.glsl
Outdated
else { | ||
lineDir = normalize(nextWindow.xy - positionWindow.xy); | ||
} | ||
angle = atan(lineDir.x, lineDir.y) - atan(1.0, 0.0); |
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.
atan
can be a performance killer.
- Can you precompute
atan(1.0, 0.0)
? I would not trust all GLSL compilers to optimize that. - What level of precision is required for this? Would it be possible to replace the other
atan
call with a taylor series expansion of a few terms? Seems like yes since it is being quantized.
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 pushed a change precomputing the atan(1.0,0.0). We could use a taylor series or a lookup table for the other atan, but I'd save that for later unless performance is a killer.
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.
Last time I tested - which was awhile ago - atan is pretty much the worse thing we can do in a shader. @bagnell said there was already inverse trig in the polyline shader, but I don't see it at quick glance.
If you're not up for it now, we'll try to make this change soon.
Hey @bagnell , we tried almost the exact same thing initially, and I think it would work fine if you were just drawing regular old lines. But I couldn't figure out a way to get it to play nice with the wide polyline aglo. I think the problem is that the length in meters actually changes along the line when you move the verts around, so you end up with funky artifacts depending on how the line rotates. Your algo also does something along the near plane where it looks like vert is pushed really far towards the near plane so you end up stretching the distance in meters artificially resulting in really wide dashes. I tried and tried but couldn't come up with something that worked so I ended up scrapping it in favor of this purely fragment based stippling. |
@bagnell I tried wrapping the block in polylinecommon with the ifdef, but it looks like just adding #define POLYLINE_DASH to the material didn't work. It behaves like it's not actually set. Is there somewhere else the define would need to go? |
@mramato for CZML, I'd think it'd be easier and more intuitive to write a bit mask instead of a 16bit number, especially for users more familiar with the data side of things. IE:
is more human read/writeable than:
|
@bagnell and @pjcozzi do you have any additional comments here? I want to take another pass on the Entity updates (just because I haven't looked at this in a few weeks) but I don't expect any surprises. Barring any issues, I would like to get this merged ASAP so that it has time to stew before 1.32 on May 1st. Thanks. |
@mramato review and merge when ready. |
Sorry, it needs to be in the vertex shader. Can you modify the |
We can probably add this in as a CZML-only feature in a small PR after this gets merged. We'll also need to update the spec and writer too. (Of course we need that for the new dash stuff as well). CC @shunter |
@jasonbeverage we'd like to merge this in the next few days so it has some time in master before it ships in Cesium 1.33 on May 1. Can you make the change @bagnell suggested, #5159 (comment), or do you want us to? Does anyone else want to test or review this? |
If you can do it that would help me out, I'm knee deep in other stuff right
now and you'll be faster at it anyway :)
…On Thu, Apr 20, 2017 at 10:55 AM Patrick Cozzi ***@***.***> wrote:
@jasonbeverage <https://github.com/jasonbeverage> we'd like to merge this
in the next few days so it has some time in master before it ships in
Cesium 1.33 on May 1. Can you make the change @bagnell
<https://github.com/bagnell> suggested, #5159 (comment)
<#5159 (comment)>,
or do you want us to?
Does anyone else want to test or review this?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#5159 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAT74gT0RL6pFeyMJwLjfO6K7fdZy8K0ks5rx3HSgaJpZM4MqyVr>
.
|
@mramato Can you merge when ready? |
I threw some fairly complex linework at it and it performed admirably. |
Thanks again @jasonbeverage! |
Thanks for merging this! Glad to be able to contribute. |
Fantastic! This will quickly become a popular feature. Thanks again @jasonbeverage! |
@jasonbeverage I had a thirst for dashed lines that you have now quenched, thankyou. |
I know I'm a bit late to the party, but I just wanted to mention that with ECMA6, the 0b format for numbers is supported. Also 0b1111111100000000 (255) if reversed and overlapped is effectively a bitwise OR that leaves you with all 1s. 0b1111000000001111 (61455) or 0b0000111111110000 (4080) is the same pattern, but is the same forwards and backwards. |
This PR adds support for screen space "dashed" polylines. This attempts to get something similar to OpenGL line stippling to work with Cesium's neat wide polyline algorithm. I tried various techniques using the texture coordinates of the line but none ended up looking as nice as this one.
There is a new PolylineDashMaterialProperty that controls the PolylineDash material.
I've modified the PolylineMaterialAppearanceVS.glsl shader to compute a varying, v_angle, that is fed to the fragment shader. This angle is the screen space angle between the line and the x axis quantized to 45 degree increments. I've quantized rather than using the actual value to try to avoid artifacts as the polyline expands.
The fragment shader takes the incoming pixel coordinate, rotates it by the incoming angle and then does a simple stippling along the x-axis on the rotated pixel coordinate. The fragment location is rotated to create a striped pattern in the direction of the line so it actually appears like it's being stippled along the line.
I've updated the Polyline and Polyline CZML sandcastle examples to have a dashed line so you can see it in action.