[英]Draw a dashed and dotted bezier curve in QML
我已經看到在QML中有一個Bezier曲線的示例實現,但我正在尋找一個如何實現虛線或點狀貝塞爾曲線的提示。 據我所知,Bezier曲線示例的作者使用QSGGeometryNode
存儲QSGGeometry
內部,並在其上應用了QSGFlatColorMaterial
材質。 然后,他們只需創建點列表並在它們之間繪制段。
是否可以編寫shader
並將其應用於QSGFlatColorMaterial
(以dashed
, dotted
線等方式顯示線條)?
最終,是可以存儲多個QSGGeometry
內QSGGeometryNode
?
UPDATE
我想在“純QtQuick
”中實現它 - 而不是在“舊”接口(如QPainter etc
)中 - 因為我不想使用切換上下文(openGL和CPU)的東西。 我更喜歡使用自定義着色器的解決方案(如果它可行) - 因為我將有更多的可能性來實現自定義外觀(虛線,溺愛,彩色,可能是動畫等)。
如果不可能,我將使用QPainter
。
我不認為這個任務是使用QSGGeometryNode
實現的好QSGGeometryNode
,使用基於QPainter
的繪圖和QQuickPaintedItem
來實現它會容易QQuickPaintedItem
。 您仍將獲得OpenGL的好處,因為QPainter
支持GL繪圖,它仍然比軟件更快。 您可以使用帶有點線或虛線圖案的庫存QPen
,或使用簡單的QVector
制作您自己的QVector
。
或者,您可以使用自定義GL繪圖方法,而不是使用Qt提供的類,這些類在表示高級復合幾何時非常有限。 您甚至可以使用實例化(如果可用)來進一步提高性能,只需沿路徑曲線定位破折號或點幾何。
最后但並非最不重要的是,您可以使用QML Canvas元素,它支持與QPainter
幾乎相同的操作,並且可能提供相同的性能。
編輯:正如您的更新所示,您錯過了我說QPainter
可以在軟件和GL中繪制的部分,而GL繪圖通常要快得多。 此外,通過繪制到GL上下文,您不必將幀緩沖區從CPU移動到GPU內存,而是將其保存在GPU內存中。 所以沒有開銷。 至於動畫和其他東西,當然, QPainter
不可能限制QPen
提供的任何QPen
- 不同的連接,大寫等可以用來在某種程度上修改形狀,但沒有奇跡......它贏了對於着色器也是可能的,只有自定義幾何體才能實現。 如果你為每個破折號/點元素使用一個基於QObject
的對象,以便獨立地為它們設置動畫,那么它最終將非常昂貴, QObject
非常重,不應該使用這樣輕的手。 因此,如果您想要這種靈活性,那么定制GL渲染到FBO幾乎是要走的路,但是您將不得不完全退出QtQuick API並進入GL領域。
無論如何,虛線着色器不應該是那么復雜,基本上你根據曲線的距離和沿着它的長度的“周期”為片段着色。 我找到了這個例子 ,自己沒試過。 您可以為閾值設置動畫,甚至使用正弦函數來獲得時髦的樣式。
至於“純粹的”QtQuick實現,API並沒有真正設計用於處理這種類型的繪圖任務,這就是為什么提供Canvas元素來填補空白並從QML / JS獲得高級痛苦功能的原因。 Canvas實際上是QPainter
的包裝器,可以吸引FBO。
最后,它不會歸結為可能/不可能的東西,但哪種方法最有意義,並且最有效地完成工作。 首先嘗試使用QQuickPaintedItem
方法,因為它是最簡單的方法,如果您對性能不滿意,可以針對第一個實現另一個更復雜的解決方案和配置文件。 畢竟,這就是為什么QQuickPaintedItem
被引入 - 處理傳統繪畫,這對QQuickItem
類來說QQuickItem
。
使用Qt 5.10,Shape元素已經被引入,並且似乎完全符合您的要求。
https://doc.qt.io/qt-5.10/qml-qtquick-shapes-shape.html
Shape {
width: 20
ShapePath {
strokeColor: "blue"
strokeWidth: 2
strokeStyle: ShapePath.DashLine
startX: 0
startY: 0
PathLine { x: parent.width; y: 0 }
}
}
你為什么不用這種方法:
修改了Beziercurve示例以使用QSGVertexColorMaterial
然后,您可以為每個vetex指定顏色和alpha,以獲得破折號,點或您選擇的任何模式。
以下是重要部分:
geometry = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), m_segmentCount);
//geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), m_segmentCount);
QSGVertexColorMaterial *material = new QSGVertexColorMaterial;
//material->setColor(QColor(255, 0, 0));
//QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D();
QSGGeometry::ColoredPoint2D *vertices = geometry->vertexDataAsColoredPoint2D();
vertices[i].set(x, y, 0, 0, 0, 0);
//vertices[i].set(x, y);
不,您不能在幾何節點中存儲多個幾何。 API非常明確。 沒有理由在那里存儲多個幾何,因為節點將幾何和材料配對。 您可以在節點之間重復使用幾何和材料 - 事實上,這就是它的使用方式。
問題的其余部分並不完整,即使提供了基於着色器的實現,它最初也不會非常有用。 這只是一個不成熟的優化。 讓我們來看看你錯過了什么。
示例BezierCurve項目只是一個概念證明。 它本身並沒有用,因為你需要一種方法來鏈接使用相同筆撫摸的多個項目。 你需要類似於簡單的QPainterPath
東西。 實際上,幾何本身可以由QPainterPath
和QPainterPathStroker
生成。
一旦您為連續描邊的項目獲得完整的細分幾何體,您就可以根據線條樣式進一步剪切它,或使用着色器。 它需要分析才能顯示線條樣式着色器本身就是一個巨大的勝利。 很可能你需要一個幾何着色器來進行撫摸等,所有的性能增益都會集中在那里。 想想要完成的計算次數,線條樣式相對簡單。
import QtQuick 2.0
Rectangle {
width : 1024
height: 600
Rectangle {
x: -3 + 158
y: 355
width: 4; height: 4;
color: "black";
}
Rectangle {
x: 359 + 158
y: 220
width: 4; height: 4;
color: "black";
}
Rectangle {
x: 175 + 158
y: 238
width: 2; height: 2;
color: "black";
}
Rectangle {
x: 711 + 158
y: 355
width: 4; height: 4;
color: "black";
}
Rectangle {
x: 533 + 158
y: 238
width: 2; height: 2;
color: "black";
}
Rectangle {
x: -3 + 118
y: 355
width: 4; height: 4;
color: "darkBlue";
}
Rectangle {
x: 399 + 118
y: 220
width: 4; height: 4;
color: "darkBlue";
}
Rectangle {
x: 196 + 118
y: 238
width: 4; height: 4;
color: "darkBlue";
}
Rectangle {
x: 791 + 118
y: 355
width: 4; height: 4;
color: "darkBlue";
}
Rectangle {
x: 592 + 118
y: 238
width: 4; height: 4;
color: "darkBlue";
}
Path {
id: path
startX: -3
startY: 355
PathQuad { x: 359; y:220; controlX: 175; controlY:238 }
PathQuad { x: 711; y:355; controlX: 533; controlY:238 }
}
Path {
id: path2
startX: -3
startY: 355
PathQuad { x: 399; y:220; controlX: 196; controlY:238 }
PathQuad { x: 791; y:355; controlX: 592; controlY:238 }
}
PathView {
id: pathView;
x: 158
width: 708
model: 300;
path: path
delegate: Rectangle {
id: dot;
width: 1; height: 1;
color: "red";
}
}
PathView {
id: pathView2;
x: 118
width: 788
model: 300;
path: path2
delegate: Rectangle {
id: dot2;
width: 1; height: 1;
color: "green";
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.