14

我已经看到QML 中有一个 Bezier 曲线的示例实现,但我正在寻找如何实现虚线或虚线贝塞尔曲线的提示。据我所知,Bezier 曲线示例的作者正在使用在其QSGGeometryNode上存储材料。然后他们只需创建点列表并在它们之间绘制线段。QSGGeometryQSGFlatColorMaterial

是否可以编写 ashader并将其应用于QSGFlatColorMaterial(将行显示为dasheddotted等)?

QSGGeometry最终,是否可以在内部存储多个QSGGeometryNode

更新

我想在“纯QtQuick”中实现这一点——而不是在“旧”接口(如QPainter etc)中——因为我不想使用切换上下文(openGL 和 CPU)的东西。我更喜欢带有自定义着色器的解决方案(如果可行的话)——因为我将有更多的可能性来实现自定义外观和感觉(虚线、点线、彩色,也许是动画等)。

如果不可能,我会使用QPainter.

4

5 回答 5

5

我不认为这个任务是实现 using 的好选择,使用基于绘图和 aQSGGeometryNode来实现它会容易得多。你仍然会得到 OpenGL 的好处,因为它也支持 GL 绘图并且它仍然比软件更快。您可以使用带有虚线或虚线图案的库存,也可以使用简单的.QPainterQQuickPaintedItemQPainterQPenQVector

或者,您可以使用自定义 GL 绘图方法,而不是使用 Qt 提供的类,这些类在表示高级复合几何时非常有限。您甚至可以使用实例化(如果可用)来进一步提高性能,并且只需沿路径曲线放置虚线或点几何图形。

最后但同样重要的是,您可以使用 QML Canvas 元素,它支持几乎相同的操作QPainter并且可能提供相同的性能。

编辑:正如您的更新所暗示的,您错过了我所说的QPainter可以在软件和 GL 中绘图的部分,而 GL 绘图通常要快得多。此外,通过绘制到 GL 上下文,您不必将帧缓冲区从 CPU 移动到 GPU 内存,它保存在 GPU 内存中。所以没有开销。至于动画和其他东西,当然,你不可能QPainter只限于提供的任何东西QPen- 可以使用不同的连接,帽等在一定程度上修改形状,但没有奇迹......它不会着色器也可以,只有自定义几何体才有可能。而且,如果您QObject为每个破折号/点元素使用一个基于对象以便独立地为它们设置动画,那么它最终会非常昂贵,QObject很重,不应该用这么轻的手使用。因此,如果您想要这种灵活性,那么自定义 GL 渲染到 FBO 几乎是可行的方法,但是您必须完全脱离 QtQuick API 并进入 GL 领域。

无论如何,虚线着色器不应该那么复杂,基本上,您可以根据与曲线的距离和沿其长度的“周期”为片段着色。我找到了这个例子,我自己没有尝试过。您可以为阈值设置动画,甚至使用正弦函数来获得时髦的样式。

至于“纯”QtQuick 实现,API 并没有真正设计用于处理此类绘图任务,这就是为什么提供 Canvas 元素来填补空白并从 QML/JS 获得高级绘图功能的原因。画布实际上是一个包装器,QPainter可以将其绘制到 FBO 上。

最后,它并没有归结为可能/不可能,而是哪种方法最有意义并且最有效地完成工作。首先尝试该QQuickPaintedItem方法,因为它是最简单的,如果您对性能不满意,您可以实施另一个更复杂的解决方案并针对第一个进行配置。毕竟,这就是为什么QQuickPaintedItem首先引入的原因 - 处理不方便在QQuickItem课堂上进行的遗留绘画。

于 2013-08-26T15:04:30.423 回答
4

在 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 }
    }
}
于 2018-05-10T19:52:47.803 回答
1

你为什么不使用这种方法:

贝塞尔曲线示例修改为使用 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);
于 2013-10-30T18:36:38.543 回答
0

不,您不能在几何节点中存储多个几何。API 对此非常明确。没有理由在此处存储多个几何图形,因为节点将几何图形和材质配对。您可以在节点之间重用几何图形和材料——事实上,这就是它的用途。

剩下的问题并不完整,即使提供了基于着色器的实现,它最初也不会很有用。这只是一个过早的优化。让我们看看你缺少什么。

示例 BezierCurve 项只是概念证明。它本身没有用,因为您需要一种链接使用同一支笔描边的多个项目的方法。您需要类似于简单的QPainterPath. 事实上,几何本身可以由QPainterPath和生成QPainterPathStroker

一旦您为连续描边的项目获得了完整的镶嵌几何图形,您就可以根据线条样式进一步切割它,或者使用着色器。它需要分析来表明线型着色器本身就是一个巨大的胜利。很可能您需要一个几何着色器来进行描边等,并且所有性能增益都将集中在那里。考虑到要完成的计算次数,线条样式相对简单。

于 2013-08-27T04:18:18.800 回答
-2
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";
    }
    }
}
于 2015-06-04T08:58:02.170 回答