I've seen there is an example implementation of a Bezier curve in QML, but I'm looking for a hint how to implement dashed or dotted bezier curve line. As far as I see, tha authors of Bezier curve example are using QSGGeometryNode
to store inside QSGGeometry
with a QSGFlatColorMaterial
material applied on it. Then they simply create list of points and draw segments between them.
Is it possible to write a shader
and apply it to QSGFlatColorMaterial
(to display line as dashed
, dotted
, etc)?
Eventually, is it possible to store more than one QSGGeometry
inside QSGGeometryNode
?
UPDATE
I would like to implement this in "pure QtQuick
" - not in "old" interfaces (like QPainter etc
) - because I do not want to use something, which switches context (openGL and CPU). I prefer the solution with custom shader (if is it doable) - because I'll have more possibilities in implementing custom look and feel (dashed, doted, colored, maybe animated etc).
If it is not possible, I'll use QPainter
.
I don't think this task is a good candidate for implementing using QSGGeometryNode
, it would be much easier to implement it using QPainter
based drawing and a QQuickPaintedItem
. You will still get the benefits of OpenGL, since QPainter
supports GL drawing as well and it is still faster than software. You can use the stock QPen
with stock dotted or dashed patterns or make your own with a simple QVector
.
Alternatively, you can go for a custom GL drawing approach instead of using the classes provided by Qt, which are pretty limited when it comes to representing advanced compound geometry. You can even use instancing (if available) to improve performance even further, and just position dashes or dot geometry along the path curve.
Last but not least, you can use a QML Canvas element, which supports pretty much the same operations as QPainter
and probably offers the same performance.
EDIT: As your update suggests, you missed the part where I said QPainter
can draw in both software and GL, with GL drawing being often significantly faster. Also, by drawing to a GL context, you don't have to move the framebuffer from CPU to GPU memory, it is kept in GPU memory. So no overhead. As for animations and the other stuff, sure, it is not possible with QPainter
you are limited to whatever QPen
provides - different joins, caps and so on can be used to modify the shape to some extent, but no miracles... It won't be possible with shaders too, it will only be possible with custom geometry. And if you use a QObject
based object for each dash/dot element in order to independently animate them, it will end up quite expenssive, QObject
is very heavy and should not be used with such light hand. So custom GL rendering to a FBO is pretty much the way to go if you want that kind of flexibility, but you will have to move completely out of the QtQuick API and into GL land.
At any rate, a dashed line shader should not be all that complex, basically you color the fragment based on the distance from the curve and the "period" along its length. I found this example, haven't tried it myself. You could animate the thresholds, even use a sine function to get funky looking styling.
As for a "pure" QtQuick implementation, the API has not really been designed to handle such type of drawing tasks, that is why the Canvas element was provided to fill the gap and get advanced paining functionality from QML/JS. The Canvas is effectively a wrapper around QPainter
that draws onto a FBO.
In the end it doesn't boil down to what is possible/impossible but which approach makes the most sense and is most efficient at getting the job done. Try the QQuickPaintedItem
approach first, since it is the easiest, if you are not happy with performance, you can implement another more complex solution and profile against the first. After all, that is why QQuickPaintedItem
was introduced in the first place - to handle legacy painting that is not convenient to do with the QQuickItem
class.