jdryg / vg-renderer

A vector graphics renderer for bgfx, based on ideas from NanoVG and ImDrawList (Dear ImGUI)
BSD 2-Clause "Simplified" License
519 stars 54 forks source link

LineCap and LineJoin #1

Closed X-Ryl669 closed 7 years ago

X-Ryl669 commented 7 years ago

I've seen it's not supported, but I wonder why ? What is the default cap and join them ? Butt and Miter ? Would it be difficult to implement it?

As I understand it, concerning line cap, except for round, it's just a coordinate offset. For round, which is quite rare, one could draw a filled ellipse there, so it's possible to do it.

Line joins either need to support clipping (with scissors) or adding a line for the bevel case.

jdryg commented 7 years ago

To be honest, the main reason I haven't implemented round caps and joins + bevel joins is because in my project I don't really have a use for them (i.e. it would look a bit better with them, as I used them initially with NanoVG, but the difference isn't that big so I can live with that).

Another reason is that it simplifies mesh generation. E.g. the required number of indices and vertices without round joins is easily calculated in all cases (filled paths and strokes with or without AA fringes). Round joins requires either correctly calculating the number of vertices/indices before generating the mesh or have the ability to overallocate and discard unused elements (e.g. assume that each round join will always needs N vertices and if it ends up using only K (K < N) return the rest to the vertex buffer).

It's not hard to implement but it complicates things a bit more than I needed for my project.

What's supported at the moment is Square + Butt caps (just an offset as you said) and Miter joins.

Clipping line joins with scissor might be a solution but scissoring each shape separately forces a new draw command to be added to the command list. Reducing draw call was the primary reason I wrote this code, so... it's not an option for me.

jdryg commented 7 years ago

In case you are still interested, I just pushed the code for round caps and joins as well as bevel joins. Still no miter limit, so miter joins never convert to bevel joins.

Needs some cleanup because I decided to break the implementation of each join type into separate functions, but it works (tested in my project where I use most of the combinations).

Performance of previous features (miter joins + square/butt caps) should be the same as before. As it's expected round joins are more expensive (require more geometry especially with AA).

X-Ryl669 commented 7 years ago

Thanks.

Still no miter limit, so miter joins never convert to bevel joins.

Is it the function called nvgMiterLimit in Nanovg? Never used it, but I guess it should not be hard to implement if you have bevel joins...

jdryg commented 7 years ago

You might not have used it but it has a default value of 4 which means that miter angles smaller than ~29 degrees get converted to bevels.

I might implement it at some point. But I have to cleanup the code first and make it more compact (a lot of the logic is shared between the various combinations).

jdryg commented 7 years ago

If you want to see what your output will be without miter limit in NanoVG, try setting the limit to a really large value.