aboutsummaryrefslogtreecommitdiffstats
path: root/examples/quick/scenegraph
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@digia.com>2012-12-12 20:11:12 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-01-07 10:44:02 +0100
commit077ad5f30446f6b3ccc38cb7f05897566f8e5eb7 (patch)
treedec3a47d3c2589b91299c2cbf975de041ed3b8bd /examples/quick/scenegraph
parentb58eb5239452d282b7209784274714b25f530a3c (diff)
Documentation for scene graph examples.
Change-Id: Idb39fc0b6d5e538b90ae8a0b98d9f4d77e1fb617 Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
Diffstat (limited to 'examples/quick/scenegraph')
-rw-r--r--examples/quick/scenegraph/customgeometry/doc/images/custom-geometry-example.pngbin0 -> 18006 bytes
-rw-r--r--examples/quick/scenegraph/customgeometry/doc/src/customgeometry.qdoc33
-rw-r--r--examples/quick/scenegraph/customgeometry/main.cpp3
-rw-r--r--examples/quick/scenegraph/openglunderqml/doc/images/openglunderqml-example.jpgbin0 -> 20640 bytes
-rw-r--r--examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc168
-rw-r--r--examples/quick/scenegraph/openglunderqml/squircle.cpp20
-rw-r--r--examples/quick/scenegraph/openglunderqml/squircle.h2
-rw-r--r--examples/quick/scenegraph/simplematerial/doc/images/simplematerial-example.jpgbin0 -> 10744 bytes
-rw-r--r--examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc180
-rw-r--r--examples/quick/scenegraph/simplematerial/main.qml38
-rw-r--r--examples/quick/scenegraph/simplematerial/simplematerial.cpp85
11 files changed, 461 insertions, 68 deletions
diff --git a/examples/quick/scenegraph/customgeometry/doc/images/custom-geometry-example.png b/examples/quick/scenegraph/customgeometry/doc/images/custom-geometry-example.png
new file mode 100644
index 0000000000..4ed20d3485
--- /dev/null
+++ b/examples/quick/scenegraph/customgeometry/doc/images/custom-geometry-example.png
Binary files differ
diff --git a/examples/quick/scenegraph/customgeometry/doc/src/customgeometry.qdoc b/examples/quick/scenegraph/customgeometry/doc/src/customgeometry.qdoc
index c226634823..7127fd0dc4 100644
--- a/examples/quick/scenegraph/customgeometry/doc/src/customgeometry.qdoc
+++ b/examples/quick/scenegraph/customgeometry/doc/src/customgeometry.qdoc
@@ -28,7 +28,8 @@
/*!
\example quick/scenegraph/customgeometry
\title Custom Geometry Example
- \ingroup examples
+ \ingroup qtquickexamples
+ \brief Shows how to implement a custom geometry in the Qt Quick Scene Graph.
\brief The custom geometry example shows how to create a QQuickItem which
uses the scene graph API to build a custom geometry for the scene
@@ -58,11 +59,11 @@
QQuickItem::updatePaintNode() which all items with custom scene
graph logic must implement.
- \e { The scene graph will on many hardware configurations be
+ \note The scene graph will on many hardware configurations be
rendering on a separate thread. It is therefore crucial that
- interaction with the scene graph happens in a controlled
- manner, first and foremost through the \l
- QQuickItem::updatePaintNode() function. }
+ interaction with the scene graph happens in a controlled manner,
+ first and foremost through the \l QQuickItem::updatePaintNode()
+ function.
\section1 BezierCurve Implementation
@@ -122,17 +123,17 @@
set which has two floats, one for x coordinates and one for y
coordinates. The second argument is the vertex count.
- \e {Custom attribute sets can also created, but that is not
- covered in this example}.
+ Custom attribute sets can also created, but that is not
+ covered in this example.
Since we do not have any special needs for memory managing the
geometry, we specify that the QSGGeometryNode should own the
geometry.
- \e {To minimize allocations, reduce memory fragmentation and
+ To minimize allocations, reduce memory fragmentation and
improve performance, it would also be possible to make the
geometry a member of a QSGGeometryNode subclass, in which case, we
- would not have set the QSGGeometryNode::OwnsGeometry flag}.
+ would not have set the QSGGeometryNode::OwnsGeometry flag.
\snippet quick/scenegraph/customgeometry/beziercurve.cpp 6
@@ -174,26 +175,32 @@
BezierCurve and make it part of the \c {CustomGeometry 1.0}
module.
+ As the bezier curve is drawn using GL_LINE_STRIP, we specify that
+ the view should be multisampled to get antialiasing. This is not
+ required, but it will make the item look a bit nicer on hardware
+ that supports it. Multisampling is not enabled by default because
+ it often results in higher memory usage.
+
\section1 Using the Item
- \snippet quick/scenegraph/customgeometry/LineTester.qml 1
+ \snippet quick/scenegraph/customgeometry/main.qml 1
Our .qml file imports the \c {QtQuick 2.0} module to get the
standard elements and also our own \c {CustomGeometry 1.0} module
which contains our newly created BezierCurve element.
- \snippet quick/scenegraph/customgeometry/LineTester.qml 2
+ \snippet quick/scenegraph/customgeometry/main.qml 2
Then we create the our root item and an instance of the
BezierCurve which we anchor to fill the root.
- \snippet quick/scenegraph/customgeometry/LineTester.qml 3
+ \snippet quick/scenegraph/customgeometry/main.qml 3
To make the example a bit more interesting we add an animation to
change the two control points in the curve. The end points stay
unchanged.
- \snippet quick/scenegraph/customgeometry/LineTester.qml 4
+ \snippet quick/scenegraph/customgeometry/main.qml 4
Finally we overlay a short text outlining what the example shows.
diff --git a/examples/quick/scenegraph/customgeometry/main.cpp b/examples/quick/scenegraph/customgeometry/main.cpp
index ea699c1c36..f2ec27d229 100644
--- a/examples/quick/scenegraph/customgeometry/main.cpp
+++ b/examples/quick/scenegraph/customgeometry/main.cpp
@@ -52,6 +52,9 @@ int main(int argc, char **argv)
qmlRegisterType<BezierCurve>("CustomGeometry", 1, 0, "BezierCurve");
QQuickView view;
+ QSurfaceFormat format;
+ format.setSamples(16);
+ view.setFormat(format);
view.setSource(QUrl("qrc:///scenegraph/customgeometry/main.qml"));
view.show();
diff --git a/examples/quick/scenegraph/openglunderqml/doc/images/openglunderqml-example.jpg b/examples/quick/scenegraph/openglunderqml/doc/images/openglunderqml-example.jpg
new file mode 100644
index 0000000000..69ee04d2ea
--- /dev/null
+++ b/examples/quick/scenegraph/openglunderqml/doc/images/openglunderqml-example.jpg
Binary files differ
diff --git a/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc b/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc
new file mode 100644
index 0000000000..5ded717e5f
--- /dev/null
+++ b/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example quick/scenegraph/openglunderqml
+ \title OpenGL Under QML
+ \ingroup qtquickexamples
+ \brief Shows how to render OpenGL under a Qt Quick scene.
+
+ \image openglunderqml-example.jpg
+
+ The OpenGL under QML example shows how an application can make use
+ of the \l QQuickWindow::beforeRendering() signal to draw custom
+ OpenGL content under a Qt Quick scene. This signal is emitted at
+ the start of every frame, before the scene graph starts its
+ rendering, thus any OpenGL draw calls that are made as a response
+ to this signal, will stack under the Qt Quick items.
+
+ As an alternative, applications that wish to render OpenGL content
+ on top of the Qt Quick scene, can do so by connecting to the \l
+ QQuickWindow::afterRendering() signal.
+
+ In this example, we will also see how it is possible to have
+ values that are exposed to QML which affect the OpenGL
+ rendering. We animate the threshold value using a NumberAnimation
+ in the QML file and this value is used by the OpenGL shader
+ program that draws the squircles.
+
+ \snippet quick/scenegraph/openglunderqml/squircle.h 1
+
+ First of all, we need a QObject with a slot to connect the signals
+ to. We subclass QQuickItem in order to use the \l
+ QQuickItem::window() which holds the window instance we want to
+ connect to.
+
+ We use two values of \c t. The variable \c m_t is the property
+ value as it exists in the GUI thread. The \c m_thread_t value is a
+ copy of \c m_t for use in the rendering thread. We need an
+ explicit copy because the scene graph can render in one thread
+ while updating properties on the GUI thread in preparation for the
+ next frame. If we had used only one value, the animation could
+ have updated the value to that of the next frame before we got a
+ chance to render it.
+
+ \note In this example, a wrong value for \c t will have minimal
+ consequences, but we emphasize that rendering and GUI thread
+ objects and values must stay separate to avoid race conditions,
+ undesired behavior and in the worst case, crashes.
+
+ Lets move on to the implementation.
+
+ \snippet quick/scenegraph/openglunderqml/squircle.cpp 7
+
+ The constructor of the \c Squircle class simply initializes the
+ values. The shader program will be initialized during rendering
+ later.
+
+ \snippet quick/scenegraph/openglunderqml/squircle.cpp 8
+
+ The property setter checks that the value has indeed changed
+ before updating its internal variable. It then calls \l
+ QQuickWindow::update() which will trigger another frame to be
+ rendered. Note that the setter might be called during
+ initialization, before the object has been entered into the scene
+ and before it has a window.
+
+ \snippet quick/scenegraph/openglunderqml/squircle.cpp 1
+ \snippet quick/scenegraph/openglunderqml/squircle.cpp 2
+
+ For our paint function to be called, we need to connect to the
+ window's signals. When Squircle object is populated into the
+ scene, the itemChange function is called with the change type \c
+ ItemSceneChange. We connect \l QQuickWindow::beforeRendering() to
+ \c paint() to do the rendering, and \l
+ QQuickWindow::beforeSynchronizing() to \c sync() to copy the state
+ of the \c t property for the upcoming frame.
+
+ \note Since the Squircle object has affinity to the GUI thread and
+ the signals are emitted from the rendering thread, it is crucial
+ that the connections are made with \l
+ Qt::DirectConnection. Failing to do so, will result in that the
+ slots are invoked on the wrong thread with no OpenGL context
+ present.
+
+ \snippet quick/scenegraph/openglunderqml/squircle.cpp 3
+
+ The default behavior of the scene graph is to clear the
+ framebuffer before rendering. Since we render before the scene
+ graph, we need to turn this clearing off. This means that we need
+ to clear ourselves in the \c paint() function.
+
+ \snippet quick/scenegraph/openglunderqml/squircle.cpp 4
+
+ The first thing we do in the \c paint() function is to
+ initialize the shader program. By initializing the shader program
+ here, we make sure that the OpenGL context is bound and that we
+ are on the correct thread.
+
+ We also connect to the QOpenGLContext::aboutToBeDestroyed()
+ signal, so that we can clean up the shader program when the
+ context is destroyed. Again, this is a \l Qt::DirectConnection as
+ all rendering related operations must happen on the rendering
+ thread.
+
+ \snippet quick/scenegraph/openglunderqml/squircle.cpp 5
+
+ We use the shader program to draw the squircle. At the end of the
+ \c paint function we release the program and disable the
+ attributes we used so that the OpenGL context is in a "clean"
+ state for the scene graph to pick it up.
+
+ \snippet quick/scenegraph/openglunderqml/squircle.cpp 6
+
+ In the \c cleanup() function we delete the program.
+
+ \snippet quick/scenegraph/openglunderqml/squircle.cpp 9
+
+ We use the \c sync() function to copy the state of the
+ object in the GUI thread into the rendering thread.
+
+ The signal is emitted on the rendering thread while the GUI
+ thread is blocked, so it is safe to simply copy the value without
+ any additional protection.
+
+ \snippet quick/scenegraph/openglunderqml/main.cpp 1
+
+ The application's \c main() function instantiates a QQuickView and
+ launches the \c main.qml file. The only thing worth noting is that
+ we export the \c Squircle class to QML using the \l
+ qmlRegisterType() macro.
+
+ \snippet quick/scenegraph/openglunderqml/main.qml 1
+
+ We import the Squircle QML type with the name we registered in the
+ \c main() function. We then instantiate it and create a running
+ NumberAnimation on the its \c t property.
+
+ \snippet quick/scenegraph/openglunderqml/main.qml 2
+
+ Then we overlay a short descriptive text, so that it is clearly
+ visible that we are in fact rendering OpenGL under our Qt Quick
+ scene.
+
+ */
diff --git a/examples/quick/scenegraph/openglunderqml/squircle.cpp b/examples/quick/scenegraph/openglunderqml/squircle.cpp
index 867ce4a7e0..e907995e7a 100644
--- a/examples/quick/scenegraph/openglunderqml/squircle.cpp
+++ b/examples/quick/scenegraph/openglunderqml/squircle.cpp
@@ -48,6 +48,8 @@
//! [7]
Squircle::Squircle()
: m_program(0)
+ , m_t(0)
+ , m_thread_t(0)
{
}
//! [7]
@@ -70,8 +72,8 @@ void Squircle::itemChange(ItemChange change, const ItemChangeData &)
{
// The ItemSceneChange event is sent when we are first attached to a window.
if (change == ItemSceneChange) {
- QQuickWindow *c = window();
- if (!c)
+ QQuickWindow *win = window();
+ if (!win)
return;
//! [1]
@@ -79,15 +81,17 @@ void Squircle::itemChange(ItemChange change, const ItemChangeData &)
// Since this call is executed on the rendering thread it must be
// a Qt::DirectConnection
//! [2]
- connect(c, SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection);
+ connect(win, SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection);
+ connect(win, SIGNAL(beforeSynchronizing()), this, SLOT(sync()), Qt::DirectConnection);
//! [2]
// If we allow QML to do the clearing, they would clear what we paint
// and nothing would show.
//! [3]
- c->setClearBeforeRendering(false);
+ win->setClearBeforeRendering(false);
}
}
+
//! [3] //! [4]
void Squircle::paint()
{
@@ -128,7 +132,7 @@ void Squircle::paint()
1, 1
};
m_program->setAttributeArray(0, GL_FLOAT, values, 2);
- m_program->setUniformValue("t", (float) m_t);
+ m_program->setUniformValue("t", (float) m_thread_t);
glViewport(0, 0, window()->width(), window()->height());
@@ -157,4 +161,10 @@ void Squircle::cleanup()
}
//! [6]
+//! [9]
+void Squircle::sync()
+{
+ m_thread_t = m_t;
+}
+//! [9]
diff --git a/examples/quick/scenegraph/openglunderqml/squircle.h b/examples/quick/scenegraph/openglunderqml/squircle.h
index 3d0a46e2ec..85e6187ae4 100644
--- a/examples/quick/scenegraph/openglunderqml/squircle.h
+++ b/examples/quick/scenegraph/openglunderqml/squircle.h
@@ -67,11 +67,13 @@ protected:
public slots:
void paint();
void cleanup();
+ void sync();
private:
QOpenGLShaderProgram *m_program;
qreal m_t;
+ qreal m_thread_t;
};
//! [1]
diff --git a/examples/quick/scenegraph/simplematerial/doc/images/simplematerial-example.jpg b/examples/quick/scenegraph/simplematerial/doc/images/simplematerial-example.jpg
new file mode 100644
index 0000000000..08db8dee4e
--- /dev/null
+++ b/examples/quick/scenegraph/simplematerial/doc/images/simplematerial-example.jpg
Binary files differ
diff --git a/examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc b/examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc
new file mode 100644
index 0000000000..20d244fe99
--- /dev/null
+++ b/examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example quick/scenegraph/simplematerial
+ \title Simple Material Example
+ \ingroup qtquickexamples
+ \brief Shows how to define a scene graph material to fill a shape.
+
+ \image simplematerial-example.jpg
+
+ In this example, we will make use of the \l
+ QSGSimpleMaterialShader class to fill a shape in the scene
+ graph. This is a convenience class intended to avoid a lot of the
+ boilerplate code required when creating materials with the \l
+ QSGMaterial, \l QSGMaterialShader and \l QSGMaterialType classes
+ directly.
+
+ A simple material consists of two parts, the material state and
+ the material shader. The material shader has one instance per
+ scene graph and contains the actual OpenGL shader program and
+ information about which attributes and uniforms it uses. The
+ material state is what we assign to each individual node, in this
+ case to give them different colors.
+
+ \snippet quick/scenegraph/simplematerial/simplematerial.cpp 1
+
+ The first thing we do when creating custom materials with the
+ simplified scheme is to create a state class. In this case the
+ state class contains only one member, a QColor. It also defines a
+ compare function which the scene graph can use to reorder the node
+ rendering.
+
+ \snippet quick/scenegraph/simplematerial/simplematerial.cpp 2
+
+ Next we define the material shader, by subclassing a template
+ instantiation of \l QSGSimpleMaterialShader with our \c State.
+
+ Then we use the macro \l QSG_DECLARE_SIMPLE_COMPARABLE_SHADER()
+ which will generate some boilerplate code for us. Since our \c
+ State class has a compare function, we declare that the states can
+ be compared. It would have been possible to remove the \c
+ State::compare() function and instead declare the shader with \l
+ QSG_DECLARE_SIMPLE_SHADER(), but this could then reduce performance
+ in certain usecases.
+
+ The state struct is used as a template parameter to
+ automatically generate a \l QSGMaterialType for us, so it is
+ crucial that the pair of shader and state are made up of unique
+ classes. Using the same \c State class in multiple shaders will
+ will lead to undefined behavior.
+
+ \snippet quick/scenegraph/simplematerial/simplematerial.cpp 3
+
+ Next comes the declaration of the shader source code, where we
+ define a vertex and fragment shader. The simple material assumes
+ the presence of \c qt_Matrix in the vertex shader and \c
+ qt_Opacity in the fragment shader.
+
+ \snippet quick/scenegraph/simplematerial/simplematerial.cpp 4
+
+ We reimplement the \c attributes function to return the name of
+ the \c aVertex and \c aTexCoord attribute names. These attributes
+ will be mapped to attribute indices 0 and 1 in the node's
+ geometry.
+
+ \snippet quick/scenegraph/simplematerial/simplematerial.cpp 6
+
+ Uniforms can be accessed either by name or by index, where index
+ is faster than name, so we reimplement the \c resolveUniforms()
+ function to find the index of the \c color uniform. We do not have
+ to worry about resolving \c qt_Opacity or \c qt_Matrix as these
+ are handled by the baseclass.
+
+ \snippet quick/scenegraph/simplematerial/simplematerial.cpp 5
+
+ The \c updateState() function is called once for every unique
+ state and we use it to update the shader program with the current
+ color. The previous state is passed in as a second parameter so
+ that the user can update only that which has changed. In our
+ usecase, where all the colors are different, the updateState will
+ be called once for every node.
+
+ \snippet quick/scenegraph/simplematerial/simplematerial.cpp 7
+
+ The \c ColorNode class is supposed to draw something, so it needs
+ to be a subclass of \l QSGGeometryNode.
+
+ Since our shader expects both a position and a texture coordinate,
+ we use the default attribute set \l
+ QSGGeometry::defaultAttributes_TexturedPoint2D() and define that
+ the geometry consists of a total of four vertices. To avoid the
+ allocation, we make the QSGGeometry a member of the
+ QSGGeometryNode.
+
+ When used the macro \l QSG_DECLARE_SIMPLE_COMPARABLE_SHADER() above,
+ it defined the \c createMaterial() function which we use to
+ instantiate materials for our \c State struct.
+
+ As we will be making use of opacity in our custom material, we
+ need to set the \l QSGMaterial::Blending flag. The scene graph may
+ use this flag to either disable or enable \c GL_BLEND when drawing
+ the node or to reorder the drawing of the node.
+
+ Finally, we tell the node to take ownership of the material, so we
+ do not have to explicitly memorymanage it.
+
+ \snippet quick/scenegraph/simplematerial/simplematerial.cpp 8
+
+ Since the Item is providing its own graphics to the scene graph,
+ we set the flag \l QQuickItem::ItemHasContents.
+
+ \snippet quick/scenegraph/simplematerial/simplematerial.cpp 9
+
+ Whenever the Item has changed graphically, the \l
+ QQuickItem::updatePaintNode() function is called.
+
+ \note The scene graph may be rendered in a different thread than the
+ GUI thread and \l QQuickItem::updatePaintNode() is one of the few
+ places where it is safe to access properties of the QML
+ object. Any interaction with the scene graph from a custom \l
+ QQuickItem should be contained to this function. The function is
+ called on the rendering thread while the GUI thread is blocked.
+
+ The first time this function is called for an \c Item instance,
+ the node will be 0 and we create a new one. For every consecutive
+ call, the node will be what we returned previously. There are
+ scenarios where the scene graph will be removed and rebuilt from
+ scratch however, so one should always check the node and recreate
+ it if required.
+
+ Once we have a \c ColorNode, we update its geometry and material
+ state. Finally, we notify the scene graph that the node has
+ undergone changes to its geometry and material.
+
+ \snippet quick/scenegraph/simplematerial/simplematerial.cpp 11
+
+ The \c main() function of the application adds the custom QML type
+ using \l qmlRegisterType() and opens up a \l QQuickView with our
+ QML file.
+
+ \snippet quick/scenegraph/simplematerial/main.qml 1
+
+ In the QML file, we import our custom type so we can instantiate
+ it.
+
+ \snippet quick/scenegraph/simplematerial/main.qml 2
+
+ Then we create a column of three instances of our custom item,
+ each with a different color.
+
+ \snippet quick/scenegraph/simplematerial/main.qml 3
+
+ And finally we overlay a short descriptive text.
+
+ */
diff --git a/examples/quick/scenegraph/simplematerial/main.qml b/examples/quick/scenegraph/simplematerial/main.qml
index 70771a7c35..b90afdd63e 100644
--- a/examples/quick/scenegraph/simplematerial/main.qml
+++ b/examples/quick/scenegraph/simplematerial/main.qml
@@ -44,30 +44,40 @@ import QtQuick 2.0
import SimpleMaterial 1.0
Rectangle {
- width: 640
- height: 360
-
- gradient: Gradient {
- GradientStop { position: 0; color: "#00ffff" }
- GradientStop { position: 1; color: "#00ff00" }
- }
+ width: 320
+ height: 480
+ color: "black"
//! [1] //! [2]
- SimpleMaterialItem {
+ Column {
anchors.fill: parent
- SequentialAnimation on scale {
- NumberAnimation { to: 100; duration: 60000; easing.type: Easing.InCubic }
- NumberAnimation { to: 1; duration: 60000; easing.type: Easing.OutCubic }
- loops: Animation.Infinite
+
+ SimpleMaterialItem {
+ width: parent.width;
+ height: parent.height / 3;
+ color: "steelblue"
+ }
+
+ SimpleMaterialItem {
+ width: parent.width;
+ height: parent.height / 3;
+ color: "darkorchid"
}
- rotation: scale * 10 - 10
+ SimpleMaterialItem {
+ width: parent.width;
+ height: parent.height / 3;
+ color: "springgreen"
+ }
}
+
+
//! [2] //! [3]
Rectangle {
color: Qt.rgba(0, 0, 0, 0.8)
radius: 10
+ antialiasing: true
border.width: 1
border.color: "black"
anchors.fill: label
@@ -78,7 +88,7 @@ Rectangle {
id: label
color: "white"
wrapMode: Text.WordWrap
- text: "The background here is implemented as one QSGGeometryNode node which uses QSGSimpleMaterial to implement a mandlebrot fractal fill"
+ text: "These three gradient boxes are colorized using a custom material."
anchors.right: parent.right
anchors.left: parent.left
anchors.bottom: parent.bottom
diff --git a/examples/quick/scenegraph/simplematerial/simplematerial.cpp b/examples/quick/scenegraph/simplematerial/simplematerial.cpp
index b7bea08260..0b4759abc8 100644
--- a/examples/quick/scenegraph/simplematerial/simplematerial.cpp
+++ b/examples/quick/scenegraph/simplematerial/simplematerial.cpp
@@ -52,11 +52,11 @@
#include <qsgsimplematerial.h>
//! [1]
-struct Color
+struct State
{
QColor color;
- int compare(const Color *other) const {
+ int compare(const State *other) const {
uint rgb = color.rgba();
uint otherRgb = other->color.rgba();
@@ -72,9 +72,9 @@ struct Color
//! [1]
//! [2]
-class Shader : public QSGSimpleMaterialShader<Color>
+class Shader : public QSGSimpleMaterialShader<State>
{
- QSG_DECLARE_SIMPLE_COMPARABLE_SHADER(Shader, Color);
+ QSG_DECLARE_SIMPLE_COMPARABLE_SHADER(Shader, State);
//! [2] //! [3]
public:
@@ -97,18 +97,8 @@ public:
"varying highp vec2 texCoord; \n"
"void main () \n"
"{ \n"
- " highp vec2 z = texCoord; \n"
- " gl_FragColor = vec4(0); \n"
- " const highp float maxIterations = 100.; \n"
- " for (float i = 0.; i < maxIterations; i += 1.0) { \n"
- " z = vec2(z.x*z.x - z.y*z.y, 2.0*z.x*z.y) + texCoord; \n"
- " if (dot(z, z) > 4.0) { \n"
- " float col = pow(1. - i / maxIterations, sqrt(maxIterations / 10.)); \n"
- " gl_FragColor = color * col * qt_Opacity; \n"
- " break; \n"
- " } \n"
- " } \n"
- "} \n";
+ " gl_FragColor = texCoord.y * texCoord.x * color * qt_Opacity; \n"
+ "}";
}
//! [3] //! [4]
QList<QByteArray> attributes() const
@@ -116,9 +106,9 @@ public:
return QList<QByteArray>() << "aVertex" << "aTexCoord";
}
//! [4] //! [5]
- void updateState(const Color *color, const Color *)
+ void updateState(const State *state, const State *)
{
- program()->setUniformValue(id_color, color->color);
+ program()->setUniformValue(id_color, state->color);
}
//! [5] //! [6]
void resolveUniforms()
@@ -128,38 +118,37 @@ public:
private:
int id_color;
-};
//! [6]
+};
//! [7]
-class TestNode : public QSGGeometryNode
+class ColorNode : public QSGGeometryNode
{
public:
- TestNode(const QRectF &bounds)
+ ColorNode()
: m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
{
- QSGGeometry::updateTexturedRectGeometry(&m_geometry, bounds, QRectF(-0.60, -0.66, 0.08, 0.04));
setGeometry(&m_geometry);
-//! [7] //! [8]
- QSGSimpleMaterial<Color> *material = Shader::createMaterial();
- material->state()->color = Qt::blue;
+ QSGSimpleMaterial<State> *material = Shader::createMaterial();
material->setFlag(QSGMaterial::Blending);
-
setMaterial(material);
setFlag(OwnsMaterial);
}
-//! [8] //! [9]
+
QSGGeometry m_geometry;
};
-//! [9]
+//! [7]
-//! [10]
+//! [8]
class Item : public QQuickItem
{
Q_OBJECT
+
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+
public:
Item()
@@ -167,17 +156,40 @@ public:
setFlag(ItemHasContents, true);
}
+ void setColor(const QColor &color) {
+ if (m_color != color) {
+ m_color = color;
+ emit colorChanged();
+ update();
+ }
+ }
+ QColor color() const {
+ return m_color;
+ }
+
+signals:
+ void colorChanged();
+
+private:
+ QColor m_color;
+
+//! [8] //! [9]
+public:
QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
{
- delete node;
- return new TestNode(boundingRect());
- }
-};
-//! [10]
+ ColorNode *n = static_cast<ColorNode *>(node);
+ if (!node)
+ n = new ColorNode();
+ QSGGeometry::updateTexturedRectGeometry(n->geometry(), boundingRect(), QRectF(0, 0, 1, 1));
+ static_cast<QSGSimpleMaterial<State>*>(n->material())->state()->color = m_color;
+ n->markDirty(QSGNode::DirtyGeometry | QSGNode::DirtyMaterial);
-//! [11]
+ return n;
+ }
+};
+//! [9] //! [11]
int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
@@ -185,11 +197,12 @@ int main(int argc, char **argv)
qmlRegisterType<Item>("SimpleMaterial", 1, 0, "SimpleMaterialItem");
QQuickView view;
+ view.setResizeMode(QQuickView::SizeRootObjectToView);
view.setSource(QUrl("qrc:///scenegraph/simplematerial/main.qml"));
view.show();
return app.exec();
}
-//! [11]
#include "simplematerial.moc"
+//! [11]