Documentation for scene graph examples.
Change-Id: Idb39fc0b6d5e538b90ae8a0b98d9f4d77e1fb617 Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
This commit is contained in:
parent
b58eb52394
commit
077ad5f304
Binary file not shown.
Before Width: | Height: | Size: 27 KiB |
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
|
@ -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.
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
|
@ -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.
|
||||
|
||||
*/
|
|
@ -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]
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
|
@ -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.
|
||||
|
||||
*/
|
|
@ -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"
|
||||
}
|
||||
|
||||
rotation: scale * 10 - 10
|
||||
SimpleMaterialItem {
|
||||
width: parent.width;
|
||||
height: parent.height / 3;
|
||||
color: "darkorchid"
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -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());
|
||||
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);
|
||||
|
||||
return n;
|
||||
}
|
||||
};
|
||||
//! [10]
|
||||
|
||||
|
||||
|
||||
//! [11]
|
||||
//! [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]
|
||||
|
|
|
@ -144,6 +144,29 @@
|
|||
\sa {Simple Material Example}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\macro QSG_DECLARE_SIMPLE_SHADER(Shader, State)
|
||||
\relates QSGSimpleMaterialShader
|
||||
|
||||
This macro is used to declare a QSGMaterialType and a \c
|
||||
createMaterial() function for \a Shader with the given \a State.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\macro QSG_DECLARE_SIMPLE_COMPARABLE_SHADER(Shader, State)
|
||||
\relates QSGSimpleMaterialShader
|
||||
|
||||
This macro is used to declare a QSGMaterialType and a \c
|
||||
createMaterial() function for \a Shader with the given \a State,
|
||||
where the \a State class must define a compare function on the
|
||||
form:
|
||||
|
||||
\code
|
||||
int compare(const State *other) const;
|
||||
\endcode
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn char const *const *QSGSimpleMaterialShader::attributeNames() const
|
||||
\internal
|
||||
|
|
Loading…
Reference in New Issue