-
-
Notifications
You must be signed in to change notification settings - Fork 35.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
Feature Suggestion: Add perspective size attenuation option to LineMaterial #16912
Conversation
Can you please see #11349 (comment) and explain again what you are proposing here? |
@WestLangley
It's true that zooming in the camera to the scene can cause a line to be large but that's the case with any 3d model and just the nature of perspective I feel. I think it should be up to the application developer to choose the right approach for their work and handle any problematic corner cases they may run into if any arise. For my use case I'd like the lines to feel more situated in world space by enabling perspective attenuation. I just made a couple quick changes to enable attenuation in the shader but I'll make any changes to the implementation that you'd like to see. And as mentioned above I'd probably rename the field on the material to |
My feeling is that lines are used to render perspective; they are not drawn in perspective. So I am not a big fan of this idea. But to continue the discussion, adding That means you will now have the following use cases to support:
|
I understand what you're saying and I definitely agree that that's a big use case but there are others that require specifying the width in world units. For comparison Unity's
I agree and I haven't tested with an orthographic camera so I'll get that done. If I put the time in to implement and test this fully with the updates we discussed will you support the change? |
Rethinking the use cases, there is no need for a
So you only need a I would not object as long as the shader code is modified in a clear manner -- and is correct. |
@WestLangley I've made the changes. When This is true even with orthographic cameras because if we consider lineWidth to be specified in world units then we should expect that a line would be the same size as a 1 unit wide block if I'm tempted to suggest that PointsMaterial should behave the same way but that can be discussed another day. |
Oof you're right -- thanks for the catch. I believe I've fixed it by deriving the line direction in screen space rather than world space. I think it looks much better now. Before After And showing that a line with a world-units width of 1 is the same width as a unit cube: At extremely skewed angles the endcaps will still have a bit of an odd look but I don't think there's much that can be done about that (Unity's LineRenderer exhibits the same behavior). |
Implementing a feature that clearly is not correct will lead to complaints. I think the correct math can be implemented with some additional effort. I would then be more supportive of this feature request. |
I'll put a bit more time into it and see what I can come up with -- any resources or direction you have on it would be greatly appreciated. And just so we're on the same page am I to understand that "correct" here means the line strip should look like a capsule when viewed from all angles?
As an aside would this be alleviated if proper docs were written for the Line2 example? Generally my feeling is that limitations like this are okay as long as they're declared up front and a user knows what to expect. Most graphics cheats break down at some point and I feel it's just a matter of knowing what those limitations are and how to avoid them. The transparency artifacts that appear on the line, for example, would also benefit from being explained up front a bit, too. Thanks again! |
No, it should look like a projected 3D capsule -- at least in theory.
No, it is only alleviated if the projection is correct. |
I've updated the shader such that a line segment looks like a projected capsule: Every resource I found indicated that the aforementioned artifacts are inherent with the projected quad technique so the render approach is now a bit more complicated. When rendering with world units the quad is projected such that the the area will cover where the capsule is projected. Then the fragment shader does a ray-line distance check and discards a pixel if the ray is too far from the line. Here's the new demo: https://rawgit.com/gkjohnson/three.js/161915d/examples/webgl_lines_fat.html The ray-line-distance check is referenced from Paul Bourke's write up on topic, which I can add an inline reference to if you want. Thanks for the push! |
@gkjohnson This definitely is the correct look. Thanks for doing this. Note that in most use cases, 99% of what is rendered are the lines themselves; the end-caps are a small part. The lines can be rendered with two triangles. Unless there is a gotcha that I am missing, that should be doable -- and a far superior approach to computing the distance to a line for every texel. I think is would involve a minimal change to the program, although I admit I have not tried it. Would you be willing to try? I can share some of the calculations I have made. You have convinced me that size attenuation is a nice feature. |
@WestLangley Awesome! Yeah it's definitely more computationally intensive than the other approach. I can look into what it might take to implement what you're suggesting but as it is there are cases where the center quad has pixels discarded because they aren't intersecting the capsule. It's definitely the case that the quad could have a tighter containment around the capsule, though. Here are some pictures illustrating the what's happening -- the green and yellow quads are the endcap tris while the magenta one are the line "body" tris you're talking about: Looking perpendicular to the line: And looking at a skewed angle: The magenta triangles are no longer centered along the line being drawn. Instead they are situated at the forward edge of the capsules surface to ensure the whole projected capsule area is contained. Clearly there are cases where the endcap quads aren't being used at all, though, and that could probably be improved. Hopefully that makes sense -- I'm definitely open to hearing what kinds of changes you're imagining, as well! I'm also interested in whether or not the logic in the shader is clear otherwise I can add some more clarifying comments or try to explain it better. |
@gkjohnson first of all, AMAZING work + shader! Is there any chance you can elaborate on the camera clipping part of the shader? Is there a way to not make it an estimate? I’ve tried to port the logic to C# + Unity and its only this part that sometimes gives me trouble in the final output on specifically lines close to the camera. |
What is the current status of this PR? |
@lauri-codes Try THREE.MeshLine. It supports size attenuation. |
Thanks for the prompt reply. The size attenuation in THREE.MeshLine does not work correctly with an orthographic camera. I had to use a fork at https://github.com/ryanking1809/threejs-meshline that seems to be have more functionality. It would, however, be great if three.js would have this feature built-in. |
FYI, I had reasons for omitting that feature, but it is not my decision to make. |
Any update on this? I've looked at using MeshLine but seems like there's no real maintainer for it now. I agree with @lauri-codes that having this built in would be awesome. I work on path planning software and we currently use the normal Line but it would look a lot nicer with a thicker line and be more usable. |
…form # Conflicts: # examples/js/lines/LineMaterial.js # examples/jsm/lines/LineMaterial.js # examples/webgl_lines_fat.html
I've just updated the PR from my more recent version over in this repo that adds alpha to coverage support and resolved conflicts . A quick note on performance because if I recall one concern about this approach that may have prevented support-- I did a quick perf comparison on my lower end 2017 Surface Laptop using the GPUStatsPanel and when adjusting the perspective lines vs the pixel lines to have roughly the same visual footprint the performance seemed to be very similar between them. Both approaches took ~1.4-1.5ms GPU time per frame. I used 5px lines for screen space lines and 0.3 unit lines for the perspective lines which had a similar look on my display but would be great if someone could verify. Regarding comments about world-space lines looking bad if the camera gets close to them I think this is up to the user to decide and usecase dependent. Many 3d models will look bad when you zoom in too far for a variety of reasons, as well. I think there are reasonable use cases that keep the camera far from the lines but benefit from perspective attenuation. Having said that the caveats as I see them at this point are that geometry intersections won't have a round profile and of course this PR doesn't add support for raycasting against world-unit lines which has now been added for screen space lines. It would be nice if this were included but I don't have strong opinions on including this at this point. That's some my updated thinking on the topic, anyway. |
I support whatever @gkjohnson wants to do. :-) |
Lets merge it then! 👍 |
Thanks! |
Adds a
screenSpaceWidth
uniform toLineMaterial
which enables or disables a consistent screen space thickness. This is similar to thesizeAttenuation
uniform onPointsMaterial
.For testing:
https://rawgit.com/gkjohnson/three.js/screen-space-lines-uniform/examples/webgl_lines_fat.html
@WestLangley