aboutsummaryrefslogtreecommitdiffstats
path: root/examples/quick/scenegraph/simplematerial
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/simplematerial
parentb58eb5239452d282b7209784274714b25f530a3c (diff)
Documentation for scene graph examples.
Change-Id: Idb39fc0b6d5e538b90ae8a0b98d9f4d77e1fb617 Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
Diffstat (limited to 'examples/quick/scenegraph/simplematerial')
-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
4 files changed, 253 insertions, 50 deletions
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]