From 077ad5f30446f6b3ccc38cb7f05897566f8e5eb7 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 12 Dec 2012 20:11:12 +0100 Subject: Documentation for scene graph examples. Change-Id: Idb39fc0b6d5e538b90ae8a0b98d9f4d77e1fb617 Reviewed-by: Yoann Lopes --- .../doc/images/custom-geometry-example.png | Bin 0 -> 18006 bytes .../customgeometry/doc/src/customgeometry.qdoc | 33 ++-- examples/quick/scenegraph/customgeometry/main.cpp | 3 + .../doc/images/openglunderqml-example.jpg | Bin 0 -> 20640 bytes .../openglunderqml/doc/src/openglunderqml.qdoc | 168 +++++++++++++++++++ .../quick/scenegraph/openglunderqml/squircle.cpp | 20 ++- .../quick/scenegraph/openglunderqml/squircle.h | 2 + .../doc/images/simplematerial-example.jpg | Bin 0 -> 10744 bytes .../simplematerial/doc/src/simplematerial.qdoc | 180 +++++++++++++++++++++ examples/quick/scenegraph/simplematerial/main.qml | 38 +++-- .../scenegraph/simplematerial/simplematerial.cpp | 85 +++++----- 11 files changed, 461 insertions(+), 68 deletions(-) create mode 100644 examples/quick/scenegraph/customgeometry/doc/images/custom-geometry-example.png create mode 100644 examples/quick/scenegraph/openglunderqml/doc/images/openglunderqml-example.jpg create mode 100644 examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc create mode 100644 examples/quick/scenegraph/simplematerial/doc/images/simplematerial-example.jpg create mode 100644 examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc (limited to 'examples/quick/scenegraph') 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 Binary files /dev/null and b/examples/quick/scenegraph/customgeometry/doc/images/custom-geometry-example.png 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("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 Binary files /dev/null and b/examples/quick/scenegraph/openglunderqml/doc/images/openglunderqml-example.jpg 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 Binary files /dev/null and b/examples/quick/scenegraph/simplematerial/doc/images/simplematerial-example.jpg 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 //! [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 +class Shader : public QSGSimpleMaterialShader { - 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 attributes() const @@ -116,9 +106,9 @@ public: return QList() << "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 *material = Shader::createMaterial(); - material->state()->color = Qt::blue; + QSGSimpleMaterial *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(node); + if (!node) + n = new ColorNode(); + QSGGeometry::updateTexturedRectGeometry(n->geometry(), boundingRect(), QRectF(0, 0, 1, 1)); + static_cast*>(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("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] -- cgit v1.2.3