【问题标题】:Draw a dashed and dotted bezier curve in QML在 QML 中绘制虚线贝塞尔曲线
【发布时间】:2013-08-21 23:19:57
【问题描述】:

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

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

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

更新

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

如果不可能,我会使用QPainter

【问题讨论】:

  • 更改贝塞尔曲线示例以根据所选线型的需要为每个子线段生成几何图形相对简单。

标签: c++ qt opengl shader qml


【解决方案1】:

我不认为这个任务适合使用QSGGeometryNode 来实现,使用基于QPainter 的绘图和QQuickPaintedItem 来实现它会容易得多。你仍然会得到 OpenGL 的好处,因为QPainter 也支持 GL 绘图并且它仍然比软件更快。您可以使用股票QPen 与股票虚线或虚线图案或使用简单的QVector 制作自己的。

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

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

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

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

至于“纯”QtQuick 实现,API 并未真正设计用于处理此类绘图任务,这就是提供 Canvas 元素以填补空白并从 QML/JS 获得高级绘图功能的原因。 Canvas 实际上是一个围绕 QPainter 的包装器,它会绘制到 FBO 上。

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

【讨论】:

  • 非常感谢,但我很想在纯 QtQuick 中实现这个 - 如果可能的话,我不想使用 QPainter。如果没有,我会使用它 - 请参阅更新的问题。如果可以编写着色器,它会比使用预定义的QPainter 样式更强大。
  • 它仍然是一个纯粹的 QtQuick 实现,QQuickPaintedItem 顾名思义是 QtQuick2 API 的一部分。您可以很容易地为QPainter 创建自定义样式模式。我也一直想知道多重几何,但似乎 API 无法做到这一点。最后,它要么是QPainter,要么是你自己渲染到一个帧缓冲区,你可以在一个矩形上绘制。我想着色器是可能的,但不是解决这个问题的最优雅的解决方案。您可能想查看在 GL 上下文中绘制的 QPainter 代码,它也使用几何图形进行绘制。
  • 感谢您的所有澄清!我正在尝试通过着色器完成此任务,因为我想对其进行动画处理,并且使用着色器更容易做到这一点。我知道 OGL Shaders 的基础,所以我写它不会有问题。唯一的问题是如何在QML 中将它与QSGFlatColorMaterial 一起使用-我会尝试找到一种方法,但是如果您知道,我将不胜感激:)
  • 当你可以简单地将任何平面颜色统一传递给你将编写虚线的着色器时,你为什么要使用QSGFlatColorMaterial
  • 好的,所以我不会 - 我是 QML 的新手,我认为它是一种“默认”材质,我们可以在其上应用着色器。你有什么简单的例子来说明如何在那里使用这种纯色制服吗?
【解决方案2】:

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

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

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

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

【讨论】:

  • 谢谢。你有任何例子,它同时使用 - QML 和着色器?我完全理解你的回答,但我是 QML 的新手,所以一个简单的例子会对我有很大帮助。
【解决方案3】:

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

Beziercurve example modified to use 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);

【讨论】:

    【解决方案4】:
    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";
        }
        }
    }
    

    【讨论】:

      【解决方案5】:

      在 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 }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-26
        • 1970-01-01
        • 2014-09-29
        • 2017-05-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多