godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
91.55k stars 21.27k forks source link

Have a way to draw polygon-lines #7242

Closed Zylann closed 7 years ago

Zylann commented 8 years ago

It would be very useful if there was a way in Godot to draw fancy lines. Using Node2D.draw_line is handy for very basic stuff, but doesn't look pretty when tracing a path, has a limited width, and transparency will show artefacts at junction points.

fancy_lines

Having a fast and efficient way of making line paths would allow, among others:

Not to mention it would be really faster than writing a GDScript implementation so it becomes more suitable for ingame generation.

bojidar-bg commented 7 years ago

(BTW, I don't know if I should really tag it as a junior job, since the round caps look hard to do :smile: )

Zylann commented 7 years ago

Round caps is a different corner tesselation, it creates a triangle fan arc instead of one or no triangle. What's more difficult is figuring out edge cases, for example what if the path has only 180 degrees angles or very tight corners + transparency. But Unity did it https://docs.unity3d.com/Manual/class-LineRenderer.html, so I assume there is a trick :)

winipcfg commented 7 years ago

http://labs.hyperandroid.com/tag/opengl-lines

Zylann commented 7 years ago

@winipcfg I was prototyping this exact same thing :D

Note: I wonder if width can also be dynamically adjusted along the line...

Edit: I have a prototype in GDScript now, but my PC decided that there will be no internet behind any provider (be it wifi or the phone I use right now), so I can't share my WIP for now :s

Edit: wow it came back, quick WIP: (I plan to port it to C++ once I'm done with creative coding)

round bevel miter

Thank you @winipcfg for the link, the interactive visuals inspired me :) I didn't took the same approach for the code though (I don't use midpoints and miter generates less geometry).

Zylann commented 7 years ago

I have something in C++ now, still work in progress but already supports the basics: https://github.com/Zylann/godot/blob/polyline/scene/2d/line_2d.cpp

bojidar-bg commented 7 years ago

@Zylann Whoa, you are too fast! Slow down a little :wink:

Zylann commented 7 years ago

I have a minor issue about colouring. At the moment I just try to expose a begin and end colour, but it produces an incorrect gradient due to the fact OpenGL interpolates on triangles. After a bit of research people mostly deal with that by adding more vertex info to create the gradient through a shader, or using a texture. I have no idea how to do that without interfering with Godot material system, so I'll probably won't improve it, unless someone has an idea :)

@bojidar-bg do you want me to slow down? I can play Minecraft in the meantime if you want, I have to continue my underwater city :D

Zylann commented 7 years ago

I'm reaching a point where UV-mapping remains to be implemented, but I fail to find something good when using the same method so far. This is what I have (joints aren't mapped yet):

uvmap_line_1

As you can see the texture is stretched. There is a way to make it keep a better aspect, but it would loose its connectivity:

uvmap_line_2

I compared with Unity's implementation, which has another drawback: the line doesn't follow the points in angles, and jumps on very tight angles/U-turns. But texturing looks better:

uvmap_line_3

So it appears there is a compromise to be made :p

Zylann commented 7 years ago

I finished a first version of texturing, but I'll probably add an option to switch to the Unity-like approach in cases offset joints are not an issue (because it's really not pretty, unless the texture is just a gradient or points are carefully chosen).

However the last thing I want to implement for Line2D is variable width. I would like to provide a FloatCurve optional resource but it doesn't exist yet, so I wonder what's best between not implementing it, or implementing a workaround that will be compatibility-broken once a FloatCurve is available. https://github.com/godotengine/godot/issues/7296

bojidar-bg commented 7 years ago

@Zylann Don't overdo it, even a more basic version might be good at first -- and you can always add features later :smile: :+1:

Zylann commented 7 years ago

If you insist, I'll push my stuff when I get back home so you can have a look :) The editor part is missing though, points have to be edited through Vector2ArrayEditor, or with a Path2D mirroring script.

Zylann commented 7 years ago

I just pushed it here: https://github.com/Zylann/godot/tree/polyline The concerned files so far are:

- scene/2d/line_2d.h
- scene/2d/line_2d.cpp
- scene/2d/line_builder.h
- scene/2d/line_builder.cpp
- scene/resources/color_ramp.cpp

The project I'm testing it on: NativePolyLine.zip

Zireael07 commented 7 years ago

What's the status of this? Did the polyline thing make it into core?

akien-mga commented 7 years ago

Yes, it was merged in #7352.

Ron5s commented 7 years ago

Id like to use a polygonal line in the Godot 3D so I can utilize the anti aliasing. If you still have the GD script implementation would you mind posting it? Im having difficulty writing my own. Thanks for the help.

Zylann commented 7 years ago

The 2D one was merged to the engine, have a look to line_builder.cpp

Ron5s commented 7 years ago

Thnak you for the reply. I did look at it and tried to convert it over to 3D but I failed. C++ and I don't get along. But thanks for your help.

Zylann commented 7 years ago

@Ron5s tbh the code isn't much complicated, but converting it to 3D could be tricky if you want to be able to see the line from any angle (it has to twist to face the camera, could be done in a shader). I think it should be a good addition in the future to have 3D trails though (and not brute-force trails like particles do now)

Ron5s commented 7 years ago

Id prefer to use the Line2D but since 2D is not anti aliased it doesn't look good to me. It doesn't have to face the camera at any angle since it will be a 2D game in the 3D engine (the camera will always be straight on). I have it working in GDscript (partially). Right now it only works with 3 points and no round joints just chamfers. Ill look at line_builder again. But it looks great with AA. Thank you for your time and for writing line_builder.

Zylann commented 7 years ago

Yeah for now you can translate the LineBuilder in GDScript, add one more dimension (with Z=0) and create an ArrayMesh out of the resulting arrays.

Ron5s commented 7 years ago

Ok ill give it a try. thank you for taking time today to answer my questions and opening Issue #12840