| /**************************************************************************** |
| ** |
| ** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the Qt3D module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** 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 The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or (at your option) the GNU General |
| ** Public license version 3 or any later version approved by the KDE Free |
| ** Qt Foundation. The licenses are as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| ** https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qtechnique.h" |
| #include "qtechnique_p.h" |
| #include "qparameter.h" |
| #include "qgraphicsapifilter.h" |
| |
| QT_BEGIN_NAMESPACE |
| |
| using namespace Qt3DCore; |
| |
| namespace Qt3DRender { |
| |
| QTechniquePrivate::QTechniquePrivate() |
| : QNodePrivate() |
| { |
| } |
| |
| QTechniquePrivate::~QTechniquePrivate() |
| { |
| } |
| |
| /*! |
| \qmltype Technique |
| \instantiates Qt3DRender::QTechnique |
| \inqmlmodule Qt3D.Render |
| \inherits Qt3DCore::QNode |
| \since 5.7 |
| \brief Encapsulates a Technique. |
| |
| A Technique specifies a set of RenderPass objects, FilterKey objects, |
| Parameter objects and a GraphicsApiFilter, which together define a |
| rendering technique the given graphics API can render. The filter keys are |
| used by TechniqueFilter to select specific techniques at specific parts of |
| the FrameGraph. If two Parameter instances with the same name are specified |
| in a Technique and a RenderPass, the one in Technique overrides the one |
| used in the RenderPass. |
| |
| When creating an Effect that targets several versions of a graphics API, it |
| is useful to create several Technique nodes each with a graphicsApiFilter |
| set to match one of the targeted versions. At runtime, the Qt3D renderer |
| will select the most appropriate Technique based on which graphics API |
| versions are supported and (if specified) the FilterKey nodes that satisfy |
| a given TechniqueFilter in the FrameGraph. |
| |
| \note When using OpenGL as the graphics API for rendering, Qt3D relies on |
| the QSurfaceFormat returned by QSurfaceFormat::defaultFormat() at runtime |
| to decide what is the most appropriate GL version available. If you need to |
| customize the QSurfaceFormat, do not forget to apply it with |
| QSurfaceFormat::setDefaultFormat(). Setting the QSurfaceFormat on the view |
| will likely have no effect on Qt3D related rendering. |
| |
| \note Technique node can not be disabled. |
| |
| \qml |
| Technique { |
| id: gl3Technique |
| parameters: [ |
| Parameter { name: "color"; value: "orange" } |
| ] |
| filterKeys: [ |
| FilterKey { name: "renderingStyle"; value: "forward" } |
| ] |
| graphicsApiFilter: { |
| api: GraphicsApiFilter.OpenGL |
| profile: GraphicsApiFilter.CoreProfile |
| majorVersion: 3 |
| minorVersion: 1 |
| } |
| renderPasses: [ |
| RenderPass { |
| id: firstPass |
| shaderProgram: ShaderProgram { |
| // ... |
| } |
| }, |
| RenderPass { |
| id: secondPass |
| shaderProgram: ShaderProgram { |
| // ... |
| } |
| } |
| ] |
| } |
| \endqml |
| |
| \sa Effect, RenderPass, TechniqueFilter |
| */ |
| |
| /*! |
| \class Qt3DRender::QTechnique |
| \inmodule Qt3DRender |
| \inherits Node |
| \since 5.7 |
| \brief Encapsulates a Technique. |
| |
| A Qt3DRender::QTechnique specifies a set of Qt3DRender::QRenderPass |
| objects, Qt3DRender::QFilterKey objects, Qt3DRender::QParameter objects and |
| a Qt3DRender::QGraphicsApiFilter, which together define a rendering |
| technique the given graphics API can render. The filter keys are used by |
| Qt3DRender::QTechniqueFilter to select specific techniques at specific |
| parts of the FrameGraph. If two QParameter instances with the same name are |
| specified in a QTechnique and a QRenderPass, the one in Technique overrides |
| the one used in the QRenderPass. |
| |
| When creating an QEffect that targets several versions of a graphics API, |
| it is useful to create several QTechnique nodes each with a |
| graphicsApiFilter set to match one of the targeted GL versions. At runtime, |
| the Qt3D renderer will select the most appropriate QTechnique based on |
| which graphics API versions are supported and (if specified) the QFilterKey |
| nodes that satisfy a given QTechniqueFilter in the FrameGraph. |
| |
| \note When using OpenGL as the graphics API for rendering, Qt3D relies on |
| the QSurfaceFormat returned by QSurfaceFormat::defaultFormat() at runtime |
| to decide what is the most appropriate GL version available. If you need to |
| customize the QSurfaceFormat, do not forget to apply it with |
| QSurfaceFormat::setDefaultFormat(). Setting the QSurfaceFormat on the view |
| will likely have no effect on Qt3D related rendering. |
| |
| \note QTechnique node can not be disabled. |
| |
| \code |
| QTechnique *gl3Technique = new QTechnique(); |
| |
| // Create the render passes |
| QRenderPass *firstPass = new QRenderPass(); |
| QRenderPass *secondPass = new QRenderPass(); |
| |
| // Add the passes to the technique |
| gl3Technique->addRenderPass(firstPass); |
| gl3Technique->addRenderPass(secondPass); |
| |
| // Set the targeted GL version for the technique |
| gl3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL); |
| gl3Technique->graphicsApiFilter()->setMajorVersion(3); |
| gl3Technique->graphicsApiFilter()->setMinorVersion(1); |
| gl3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile); |
| |
| // Create a FilterKey |
| QFilterKey *filterKey = new QFilterKey(); |
| filterKey->setName(QStringLiteral("name")); |
| fitlerKey->setValue(QStringLiteral("zFillPass")); |
| |
| // Add the FilterKey to the Technique |
| gl3Technique->addFilterKey(filterKey); |
| |
| // Create a QParameter |
| QParameter *colorParameter = new QParameter(QStringLiteral("color"), QColor::fromRgbF(0.0f, 0.0f, 1.0f, 1.0f)); |
| |
| // Add parameter to technique |
| gl3Technique->addParameter(colorParameter); |
| \endcode |
| |
| \sa QEffect, QRenderPass, QTechniqueFilter |
| */ |
| |
| /*! |
| \qmlproperty GraphicsApiFilter Qt3D.Render::Technique::graphicsApiFilter |
| Specifies the graphics API filter being used |
| */ |
| /*! |
| \qmlproperty list<FilterKey> Qt3D.Render::Technique::filterKeys |
| Specifies the list of filter keys enabling this technique |
| */ |
| /*! |
| \qmlproperty list<RenderPass> Qt3D.Render::Technique::renderPasses |
| Specifies the render passes used by the tehcnique |
| */ |
| /*! |
| \qmlproperty list<Parameter> Qt3D.Render::Technique::parameters |
| Specifies the parameters used by the technique |
| */ |
| /*! |
| \property Qt3DRender::QTechnique::graphicsApiFilter |
| Specifies the graphics API filter being used |
| */ |
| |
| QTechnique::QTechnique(QNode *parent) |
| : QNode(*new QTechniquePrivate, parent) |
| { |
| Q_D(QTechnique); |
| QObject::connect(&d->m_graphicsApiFilter, SIGNAL(graphicsApiFilterChanged()), this, SLOT(_q_graphicsApiFilterChanged())); |
| } |
| |
| /*! \internal */ |
| QTechnique::~QTechnique() |
| { |
| } |
| |
| /*! \internal */ |
| QTechnique::QTechnique(QTechniquePrivate &dd, QNode *parent) |
| : QNode(dd, parent) |
| { |
| Q_D(QTechnique); |
| QObject::connect(&d->m_graphicsApiFilter, SIGNAL(graphicsApiFilterChanged()), this, SLOT(_q_graphicsApiFilterChanged())); |
| } |
| |
| /*! \internal */ |
| void QTechniquePrivate::_q_graphicsApiFilterChanged() |
| { |
| update(); |
| } |
| |
| /*! |
| Add \a filterKey to the Qt3DRender::QTechnique local filter keys. |
| */ |
| void QTechnique::addFilterKey(QFilterKey *filterKey) |
| { |
| Q_ASSERT(filterKey); |
| Q_D(QTechnique); |
| if (!d->m_filterKeys.contains(filterKey)) { |
| d->m_filterKeys.append(filterKey); |
| |
| // Ensures proper bookkeeping |
| d->registerDestructionHelper(filterKey, &QTechnique::removeFilterKey, d->m_filterKeys); |
| |
| // We need to add it as a child of the current node if it has been declared inline |
| // Or not previously added as a child of the current node so that |
| // 1) The backend gets notified about it's creation |
| // 2) When the current node is destroyed, it gets destroyed as well |
| if (!filterKey->parent()) |
| filterKey->setParent(this); |
| |
| d->updateNode(filterKey, "filterKeys", Qt3DCore::PropertyValueAdded); |
| } |
| } |
| |
| /*! |
| Removes \a filterKey from the Qt3DRender::QTechnique local filter keys. |
| */ |
| void QTechnique::removeFilterKey(QFilterKey *filterKey) |
| { |
| Q_ASSERT(filterKey); |
| Q_D(QTechnique); |
| d->updateNode(filterKey, "filterKeys", Qt3DCore::PropertyValueRemoved); |
| d->m_filterKeys.removeOne(filterKey); |
| // Remove bookkeeping connection |
| d->unregisterDestructionHelper(filterKey); |
| } |
| |
| /*! |
| Returns the list of Qt3DCore::QFilterKey key objects making up the filter keys |
| of the Qt3DRender::QTechnique. |
| */ |
| QVector<QFilterKey *> QTechnique::filterKeys() const |
| { |
| Q_D(const QTechnique); |
| return d->m_filterKeys; |
| } |
| |
| /*! |
| Add \a parameter to the technique's parameters. |
| */ |
| void QTechnique::addParameter(QParameter *parameter) |
| { |
| Q_ASSERT(parameter); |
| Q_D(QTechnique); |
| if (!d->m_parameters.contains(parameter)) { |
| d->m_parameters.append(parameter); |
| |
| // Ensures proper bookkeeping |
| d->registerDestructionHelper(parameter, &QTechnique::removeParameter, d->m_parameters); |
| |
| // We need to add it as a child of the current node if it has been declared inline |
| // Or not previously added as a child of the current node so that |
| // 1) The backend gets notified about it's creation |
| // 2) When the current node is destroyed, the child parameters get destroyed as well |
| if (!parameter->parent()) |
| parameter->setParent(this); |
| |
| d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded); |
| } |
| } |
| |
| /*! |
| Remove \a parameter from the technique's parameters. |
| */ |
| void QTechnique::removeParameter(QParameter *parameter) |
| { |
| Q_ASSERT(parameter); |
| Q_D(QTechnique); |
| d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved); |
| d->m_parameters.removeOne(parameter); |
| // Remove bookkeeping connection |
| d->unregisterDestructionHelper(parameter); |
| } |
| |
| /*! |
| Appends a \a pass to the technique. |
| */ |
| void QTechnique::addRenderPass(QRenderPass *pass) |
| { |
| Q_ASSERT(pass); |
| Q_D(QTechnique); |
| if (!d->m_renderPasses.contains(pass)) { |
| d->m_renderPasses.append(pass); |
| |
| // Ensures proper bookkeeping |
| d->registerDestructionHelper(pass, &QTechnique::removeRenderPass, d->m_renderPasses); |
| |
| // We need to add it as a child of the current node if it has been declared inline |
| // Or not previously added as a child of the current node so that |
| // 1) The backend gets notified about it's creation |
| // 2) When the current node is destroyed, it gets destroyed as well |
| if (!pass->parent()) |
| pass->setParent(this); |
| |
| d->updateNode(pass, "pass", Qt3DCore::PropertyValueAdded); |
| } |
| } |
| |
| /*! |
| Removes a \a pass from the technique. |
| */ |
| void QTechnique::removeRenderPass(QRenderPass *pass) |
| { |
| Q_ASSERT(pass); |
| Q_D(QTechnique); |
| d->updateNode(pass, "pass", Qt3DCore::PropertyValueAdded); |
| d->m_renderPasses.removeOne(pass); |
| // Remove bookkeeping connection |
| d->unregisterDestructionHelper(pass); |
| } |
| |
| /*! |
| Returns the list of render passes contained in the technique. |
| */ |
| QVector<QRenderPass *> QTechnique::renderPasses() const |
| { |
| Q_D(const QTechnique); |
| return d->m_renderPasses; |
| } |
| |
| /*! |
| Returns a vector of the techniques current parameters |
| */ |
| QVector<QParameter *> QTechnique::parameters() const |
| { |
| Q_D(const QTechnique); |
| return d->m_parameters; |
| } |
| |
| QGraphicsApiFilter *QTechnique::graphicsApiFilter() |
| { |
| Q_D(QTechnique); |
| return &d->m_graphicsApiFilter; |
| } |
| |
| const QGraphicsApiFilter *QTechnique::graphicsApiFilter() const |
| { |
| Q_D(const QTechnique); |
| return &d->m_graphicsApiFilter; |
| } |
| |
| Qt3DCore::QNodeCreatedChangeBasePtr QTechnique::createNodeCreationChange() const |
| { |
| auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QTechniqueData>::create(this); |
| QTechniqueData &data = creationChange->data; |
| |
| Q_D(const QTechnique); |
| data.graphicsApiFilterData = QGraphicsApiFilterPrivate::get(const_cast<QGraphicsApiFilter *>(&d->m_graphicsApiFilter))->m_data; |
| data.filterKeyIds = qIdsForNodes(d->m_filterKeys); |
| data.parameterIds = qIdsForNodes(d->m_parameters); |
| data.renderPassIds = qIdsForNodes(d->m_renderPasses); |
| |
| return creationChange; |
| } |
| |
| } // of namespace Qt3DRender |
| |
| QT_END_NAMESPACE |
| |
| #include "moc_qtechnique.cpp" |