1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the examples of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24** * Redistributions of source code must retain the above copyright
25** notice, this list of conditions and the following disclaimer.
26** * Redistributions in binary form must reproduce the above copyright
27** notice, this list of conditions and the following disclaimer in
28** the documentation and/or other materials provided with the
29** distribution.
30** * Neither the name of The Qt Company Ltd nor the names of its
31** contributors may be used to endorse or promote products derived
32** from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51#include "linenode.h"
52
53#include <QtGui/QColor>
54
55#include <QtQuick/QSGSimpleMaterial>
56
57struct LineMaterial
58{
59 QColor color;
60 float spread;
61 float size;
62};
63
64class LineShader : public QSGSimpleMaterialShader<LineMaterial>
65{
66 QSG_DECLARE_SIMPLE_SHADER(LineShader, LineMaterial)
67
68public:
69 LineShader() {
70 setShaderSourceFile(type: QOpenGLShader::Vertex, sourceFile: ":/scenegraph/graph/shaders/line.vsh");
71 setShaderSourceFile(type: QOpenGLShader::Fragment, sourceFile: ":/scenegraph/graph/shaders/line.fsh");
72 }
73
74 QList<QByteArray> attributes() const override { return QList<QByteArray>() << "pos" << "t"; }
75
76 void updateState(const LineMaterial *m, const LineMaterial *) override {
77 program()->setUniformValue(location: id_color, color: m->color);
78 program()->setUniformValue(location: id_spread, value: m->spread);
79 program()->setUniformValue(location: id_size, value: m->size);
80 }
81
82 void resolveUniforms() override {
83 id_spread = program()->uniformLocation(name: "spread");
84 id_size = program()->uniformLocation(name: "size");
85 id_color = program()->uniformLocation(name: "color");
86 }
87
88private:
89 int id_color = -1;
90 int id_spread = -1;
91 int id_size = -1;
92};
93
94struct LineVertex {
95 float x;
96 float y;
97 float t;
98 inline void set(float xx, float yy, float tt) { x = xx; y = yy; t = tt; }
99};
100
101static const QSGGeometry::AttributeSet &attributes()
102{
103 static QSGGeometry::Attribute attr[] = {
104 QSGGeometry::Attribute::create(pos: 0, tupleSize: 2, GL_FLOAT, isPosition: true),
105 QSGGeometry::Attribute::create(pos: 1, tupleSize: 1, GL_FLOAT)
106 };
107 static QSGGeometry::AttributeSet set = { .count: 2, .stride: 3 * sizeof(float), .attributes: attr };
108 return set;
109}
110
111LineNode::LineNode(float size, float spread, const QColor &color)
112 : m_geometry(attributes(), 0)
113{
114 setGeometry(&m_geometry);
115 m_geometry.setDrawingMode(GL_TRIANGLE_STRIP);
116
117 QSGSimpleMaterial<LineMaterial> *m = LineShader::createMaterial();
118 m->state()->color = color;
119 m->state()->size = size;
120 m->state()->spread = spread;
121 m->setFlag(flags: QSGMaterial::Blending);
122 setMaterial(m);
123 setFlag(OwnsMaterial);
124}
125
126/*
127 * Assumes that samples have values in the range of 0 to 1 and scales them to
128 * the height of bounds. The samples are stretched out horizontally along the
129 * width of the bounds.
130 *
131 * The position of each pair of points is identical, but we use the third value
132 * "t" to shift the point up or down and to add antialiasing.
133 */
134void LineNode::updateGeometry(const QRectF &bounds, const QList<qreal> &samples)
135{
136 m_geometry.allocate(vertexCount: samples.size() * 2);
137
138 float x = bounds.x();
139 float y = bounds.y();
140 float w = bounds.width();
141 float h = bounds.height();
142
143 float dx = w / (samples.size() - 1);
144
145 LineVertex *v = (LineVertex *) m_geometry.vertexData();
146 for (int i=0; i<samples.size(); ++i) {
147 v[i*2+0].set(xx: x + dx * i, yy: y + samples.at(i) * h, tt: 0);
148 v[i*2+1].set(xx: x + dx * i, yy: y + samples.at(i) * h, tt: 1);
149 }
150
151 markDirty(bits: QSGNode::DirtyGeometry);
152}
153

source code of qtdeclarative/examples/quick/scenegraph/graph/linenode.cpp