簡體   English   中英

在QML中繪制虛線和點線貝塞爾曲線

[英]Draw a dashed and dotted bezier curve in QML

我已經看到在QML有一個Bezier曲線的示例實現,但我正在尋找一個如何實現虛線或點狀貝塞爾曲線的提示。 據我所知,Bezier曲線示例的作者使用QSGGeometryNode存儲QSGGeometry內部,並在其上應用了QSGFlatColorMaterial材質。 然后,他們只需創建點列表並在它們之間繪制段。

是否可以編寫shader並將其應用於QSGFlatColorMaterial (以dasheddotted線等方式顯示線條)?

最終,是可以存儲多個QSGGeometryQSGGeometryNode

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東西。 實際上,幾何本身可以由QPainterPathQPainterPathStroker生成。

一旦您為連續描邊的項目獲得完整的細分幾何體,您就可以根據線條樣式進一步剪切它,或使用着色器。 它需要分析才能顯示線條樣式着色器本身就是一個巨大的勝利。 很可能你需要一個幾何着色器來進行撫摸等,所有的性能增益都會集中在那里。 想想要完成的計算次數,線條樣式相對簡單。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM