diff options
author | Sean Harmer <sean.harmer@kdab.com> | 2016-08-14 09:23:05 +0100 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2016-08-14 09:41:21 +0100 |
commit | 9a18925b63d47a20d7b74cfd508d7ae71f2d4d7c (patch) | |
tree | 4d0d0538b9475a9104d56ee3d07f4bab7b0e00b4 /src/render | |
parent | 9a1c0c96246126d2377bd56ed702f47214e3ee0a (diff) | |
parent | 71eee85093ba807f5bc2add472b359841faa062d (diff) |
Merge branch '5.7' into dev
Change-Id: Id62e225062a030f4864fb7af2ed6f60d6be87460
Diffstat (limited to 'src/render')
38 files changed, 569 insertions, 353 deletions
diff --git a/src/render/backend/entity.cpp b/src/render/backend/entity.cpp index 7091d493f..095a5a62d 100644 --- a/src/render/backend/entity.cpp +++ b/src/render/backend/entity.cpp @@ -50,7 +50,6 @@ #include <Qt3DRender/qgeometryrenderer.h> #include <Qt3DRender/qobjectpicker.h> #include <Qt3DRender/qcomputecommand.h> -#include <Qt3DRender/private/qboundingvolumedebug_p.h> #include <Qt3DRender/private/geometryrenderermanager_p.h> #include <Qt3DRender/qcameralens.h> diff --git a/src/render/backend/handle_types_p.h b/src/render/backend/handle_types_p.h index d22ef1d90..e68f0f1c5 100644 --- a/src/render/backend/handle_types_p.h +++ b/src/render/backend/handle_types_p.h @@ -114,7 +114,7 @@ typedef Qt3DCore::QHandle<Parameter, 16> HParameter; typedef Qt3DCore::QHandle<ShaderData, 16> HShaderData; typedef Qt3DCore::QHandle<TextureImage, 16> HTextureImage; typedef Qt3DCore::QHandle<Buffer, 16> HBuffer; -typedef Qt3DCore::QHandle<Attribute, 16> HAttribute; +typedef Qt3DCore::QHandle<Attribute, 20> HAttribute; typedef Qt3DCore::QHandle<Geometry, 16> HGeometry; typedef Qt3DCore::QHandle<GeometryRenderer, 16> HGeometryRenderer; typedef Qt3DCore::QHandle<ObjectPicker, 16> HObjectPicker; diff --git a/src/render/backend/managers_p.h b/src/render/backend/managers_p.h index f2c26fd00..8d922c0d1 100644 --- a/src/render/backend/managers_p.h +++ b/src/render/backend/managers_p.h @@ -310,7 +310,7 @@ class TextureImageManager : public Qt3DCore::QResourceManager< class AttributeManager : public Qt3DCore::QResourceManager< Attribute, Qt3DCore::QNodeId, - 16, + 20, Qt3DCore::ArrayAllocatingPolicy, Qt3DCore::ObjectLevelLockingPolicy> { diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp index 58cc4c483..c91eff86e 100644 --- a/src/render/backend/renderer.cpp +++ b/src/render/backend/renderer.cpp @@ -290,6 +290,12 @@ void Renderer::shutdown() { qCDebug(Backend) << Q_FUNC_INFO << "Requesting renderer shutdown"; m_running.store(0); + + // We delete any renderqueue that we may not have had time to render + // before the surface was destroyed + qDeleteAll(m_renderQueue->nextFrameQueue()); + m_renderQueue->reset(); + if (!m_renderThread) { releaseGraphicsResources(); } else { @@ -760,12 +766,19 @@ void Renderer::updateGLResources() } } - const QVector<HShader> activeShaderHandles = m_nodesManager->shaderManager()->activeHandles(); - for (HShader handle: activeShaderHandles) { - Shader *shader = m_nodesManager->shaderManager()->data(handle); - if (!shader->isLoaded()) { - // Compile shader - m_graphicsContext->loadShader(shader); + const QVector<HTechnique> activeTechniques = m_nodesManager->techniqueManager()->activeHandles(); + for (HTechnique techniqueHandle : activeTechniques) { + Technique *technique = m_nodesManager->techniqueManager()->data(techniqueHandle); + // If api of the renderer matches the one from the technique + if (*contextInfo() == *technique->graphicsApiFilter()) { + const auto passIds = technique->renderPasses(); + for (const QNodeId passId : passIds) { + RenderPass *renderPass = m_nodesManager->renderPassManager()->lookupResource(passId); + HShader shaderHandle = m_nodesManager->shaderManager()->lookupHandle(renderPass->shaderProgram()); + Shader *shader = m_nodesManager->shaderManager()->data(shaderHandle); + if (shader != nullptr && !shader->isLoaded()) + m_graphicsContext->loadShader(shader); + } } } @@ -798,6 +811,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren QSurface *surface = nullptr; QSurface *previousSurface = renderViews.first()->surface(); QSurface *lastUsedSurface = nullptr; + for (int i = 0; i < renderViewsCount; ++i) { // Initialize GraphicsContext for drawing // If the RenderView has a RenderStateSet defined @@ -842,13 +856,14 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren lastBoundFBOId = m_graphicsContext->boundFrameBufferObject(); } - // Set RenderView render state // Note: the RenderStateSet is allocated once per RV if needed // and it contains a list of StateVariant value types RenderStateSet *renderViewStateSet = renderView->stateSet(); - if (renderViewStateSet) + + // Set the RV state if not null, + if (renderViewStateSet != nullptr) m_graphicsContext->setCurrentStateSet(renderViewStateSet); - else if (surfaceHasChanged || i == 0) // Reset state to the default state on initial render view or on surface change + else m_graphicsContext->setCurrentStateSet(m_defaultRenderStateSet); // Set RenderTarget ... diff --git a/src/render/backend/renderer_p.h b/src/render/backend/renderer_p.h index ddbc4cffc..3e6ef6ffc 100644 --- a/src/render/backend/renderer_p.h +++ b/src/render/backend/renderer_p.h @@ -82,7 +82,6 @@ #include <QAtomicInt> #include <QScopedPointer> #include <QSemaphore> -#include <QThreadStorage> QT_BEGIN_NAMESPACE diff --git a/src/render/backend/renderview.cpp b/src/render/backend/renderview.cpp index 8d40f2882..9226f8fac 100644 --- a/src/render/backend/renderview.cpp +++ b/src/render/backend/renderview.cpp @@ -114,12 +114,14 @@ RenderView::StandardUniformsPFuncsHash RenderView::initializeStandardUniformSett setters.insert(StringToInt::lookupId(QLatin1String("viewMatrix")), &RenderView::viewMatrix); setters.insert(StringToInt::lookupId(QLatin1String("projectionMatrix")), &RenderView::projectionMatrix); setters.insert(StringToInt::lookupId(QLatin1String("modelView")), &RenderView::modelViewMatrix); + setters.insert(StringToInt::lookupId(QLatin1String("viewProjectionMatrix")), &RenderView::viewProjectionMatrix); setters.insert(StringToInt::lookupId(QLatin1String("modelViewProjection")), &RenderView::modelViewProjectionMatrix); setters.insert(StringToInt::lookupId(QLatin1String("mvp")), &RenderView::modelViewProjectionMatrix); setters.insert(StringToInt::lookupId(QLatin1String("inverseModelMatrix")), &RenderView::inverseModelMatrix); setters.insert(StringToInt::lookupId(QLatin1String("inverseViewMatrix")), &RenderView::inverseViewMatrix); setters.insert(StringToInt::lookupId(QLatin1String("inverseProjectionMatrix")), &RenderView::inverseProjectionMatrix); setters.insert(StringToInt::lookupId(QLatin1String("inverseModelView")), &RenderView::inverseModelViewMatrix); + setters.insert(StringToInt::lookupId(QLatin1String("inverseViewProjectionMatrix")), &RenderView::inverseViewProjectionMatrix); setters.insert(StringToInt::lookupId(QLatin1String("inverseModelViewProjection")), &RenderView::inverseModelViewProjectionMatrix); setters.insert(StringToInt::lookupId(QLatin1String("modelNormalMatrix")), &RenderView::modelNormalMatrix); setters.insert(StringToInt::lookupId(QLatin1String("modelViewNormal")), &RenderView::modelViewNormalMatrix); @@ -151,6 +153,12 @@ QUniformValue RenderView::modelViewMatrix(const QMatrix4x4 &model) const return QUniformValue(QVariant::fromValue(m_data.m_viewMatrix * model)); } +QUniformValue RenderView::viewProjectionMatrix(const QMatrix4x4 &model) const +{ + Q_UNUSED(model); + return QUniformValue(QVariant::fromValue(m_data.m_renderCameraLens->projection() * m_data.m_viewMatrix)); +} + QUniformValue RenderView::modelViewProjectionMatrix(const QMatrix4x4 &model) const { return QUniformValue(QVariant::fromValue(m_data.m_viewProjectionMatrix * model)); @@ -179,6 +187,13 @@ QUniformValue RenderView::inverseModelViewMatrix(const QMatrix4x4 &model) const return QUniformValue(QVariant::fromValue((m_data.m_viewMatrix * model).inverted())); } +QUniformValue RenderView::inverseViewProjectionMatrix(const QMatrix4x4 &model) const +{ + Q_UNUSED(model); + const auto viewProjectionMatrix = m_data.m_renderCameraLens->projection() * m_data.m_viewMatrix; + return QUniformValue(QVariant::fromValue(viewProjectionMatrix.inverted())); +} + QUniformValue RenderView::inverseModelViewProjectionMatrix(const QMatrix4x4 &model) const { return QUniformValue(QVariant::fromValue((m_data.m_viewProjectionMatrix * model).inverted(0))); @@ -383,6 +398,13 @@ void RenderView::addClearBuffers(const ClearBuffers *cb) { // If we are there, we know that entity had a GeometryRenderer + Material QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entity *> &entities) const { + // Note: since many threads can be building render commands + // we need to ensure that the UniformBlockValueBuilder they are using + // is only accessed from the same thread + UniformBlockValueBuilder *builder = new UniformBlockValueBuilder(); + builder->shaderDataManager = m_manager->shaderDataManager(); + m_localData.setLocalData(builder); + QVector<RenderCommand *> commands; commands.reserve(entities.size()); @@ -429,6 +451,8 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit std::sort(lightSources.begin(), lightSources.end(), LightSourceCompare(node)); ParameterInfoList globalParameters = passData.parameterInfo; + // setShaderAndUniforms can initialize a localData + // make sure this is cleared before we leave this function setShaderAndUniforms(command, pass, globalParameters, *(node->worldTransform()), lightSources.mid(0, std::max(lightSources.size(), MAX_LIGHTS))); buildSortingKey(command); @@ -436,11 +460,22 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit } } } + + // We reset the local data once we are done with it + m_localData.setLocalData(nullptr); + return commands; } QVector<RenderCommand *> RenderView::buildComputeRenderCommands(const QVector<Entity *> &entities) const { + // Note: since many threads can be building render commands + // we need to ensure that the UniformBlockValueBuilder they are using + // is only accessed from the same thread + UniformBlockValueBuilder *builder = new UniformBlockValueBuilder(); + builder->shaderDataManager = m_manager->shaderDataManager(); + m_localData.setLocalData(builder); + // If the RenderView contains only a ComputeDispatch then it cares about // A ComputeDispatch is also implicitely a NoDraw operation // enabled flag @@ -477,6 +512,10 @@ QVector<RenderCommand *> RenderView::buildComputeRenderCommands(const QVector<En } } } + + // We reset the local data once we are done with it + m_localData.setLocalData(nullptr); + return commands; } @@ -612,28 +651,22 @@ void RenderView::setShaderStorageValue(ShaderParameterPack &uniformPack, void RenderView::setDefaultUniformBlockShaderDataValue(ShaderParameterPack &uniformPack, Shader *shader, ShaderData *shaderData, const QString &structName) const { - // Note: since many threads can be building render commands - // we need to ensure that the UniformBlockValueBuilder they are using - // is only accessed from the same thread - if (!m_localData.hasLocalData()) { - m_localData.setLocalData(UniformBlockValueBuilder()); - m_localData.localData().shaderDataManager = m_manager->shaderDataManager(); - } - - UniformBlockValueBuilder &builder = m_localData.localData(); - builder.activeUniformNamesToValue.clear(); + UniformBlockValueBuilder *builder = m_localData.localData(); + builder->activeUniformNamesToValue.clear(); // updates transformed properties; + // Fix me: this will lead to races when having multiple cameras shaderData->updateViewTransform(m_data.m_viewMatrix); + // Force to update the whole block - builder.updatedPropertiesOnly = false; + builder->updatedPropertiesOnly = false; // Retrieve names and description of each active uniforms in the uniform block - builder.uniforms = shader->activeUniformsForUniformBlock(-1); + builder->uniforms = shader->activeUniformsForUniformBlock(-1); // Build name-value map for the block - builder.buildActiveUniformNameValueMapStructHelper(shaderData, structName); + builder->buildActiveUniformNameValueMapStructHelper(shaderData, structName); // Set uniform values for each entrie of the block name-value map - QHash<int, QVariant>::const_iterator activeValuesIt = builder.activeUniformNamesToValue.constBegin(); - const QHash<int, QVariant>::const_iterator activeValuesEnd = builder.activeUniformNamesToValue.constEnd(); + QHash<int, QVariant>::const_iterator activeValuesIt = builder->activeUniformNamesToValue.constBegin(); + const QHash<int, QVariant>::const_iterator activeValuesEnd = builder->activeUniformNamesToValue.constEnd(); while (activeValuesIt != activeValuesEnd) { setUniformValue(uniformPack, activeValuesIt.key(), activeValuesIt.value()); diff --git a/src/render/backend/renderview_p.h b/src/render/backend/renderview_p.h index 0b01744e9..7be9903f6 100644 --- a/src/render/backend/renderview_p.h +++ b/src/render/backend/renderview_p.h @@ -242,7 +242,7 @@ private: void setShaderAndUniforms(RenderCommand *command, RenderPass *pass, ParameterInfoList ¶meters, const QMatrix4x4 &worldTransform, const QVector<LightSource> &activeLightSources) const; - mutable QThreadStorage<UniformBlockValueBuilder> m_localData; + mutable QThreadStorage<UniformBlockValueBuilder*> m_localData; Renderer *m_renderer; NodeManagers *m_manager; @@ -282,11 +282,13 @@ private: QUniformValue viewMatrix(const QMatrix4x4&) const; QUniformValue projectionMatrix(const QMatrix4x4 &) const; QUniformValue modelViewMatrix(const QMatrix4x4 &model) const; + QUniformValue viewProjectionMatrix(const QMatrix4x4 &model) const; QUniformValue modelViewProjectionMatrix(const QMatrix4x4 &model) const; QUniformValue inverseModelMatrix(const QMatrix4x4 &model) const; QUniformValue inverseViewMatrix(const QMatrix4x4 &) const; QUniformValue inverseProjectionMatrix(const QMatrix4x4 &) const; QUniformValue inverseModelViewMatrix(const QMatrix4x4 &model) const; + QUniformValue inverseViewProjectionMatrix(const QMatrix4x4 &model) const; QUniformValue inverseModelViewProjectionMatrix(const QMatrix4x4 &model) const; QUniformValue modelNormalMatrix(const QMatrix4x4 &model) const; QUniformValue modelViewNormalMatrix(const QMatrix4x4 &model) const; diff --git a/src/render/framegraph/qrendersurfaceselector.cpp b/src/render/framegraph/qrendersurfaceselector.cpp index 349ceb827..e76963e72 100644 --- a/src/render/framegraph/qrendersurfaceselector.cpp +++ b/src/render/framegraph/qrendersurfaceselector.cpp @@ -43,7 +43,9 @@ #include <QtGui/QWindow> #include <QtGui/QScreen> #include <QtGui/QOffscreenSurface> +#include <Qt3DCore/qentity.h> #include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DRender/qrendersettings.h> QT_BEGIN_NAMESPACE @@ -104,6 +106,30 @@ QRenderSurfaceSelectorPrivate::~QRenderSurfaceSelectorPrivate() QObject::disconnect(m_screenConn); } +QRenderSurfaceSelector *QRenderSurfaceSelectorPrivate::find(QObject *rootObject) +{ + auto rendererSettings = rootObject->findChild<Qt3DRender::QRenderSettings *>(); + if (!rendererSettings) { + qWarning() << "No renderer settings component found"; + return nullptr; + } + + auto frameGraphRoot = rendererSettings->activeFrameGraph(); + if (!frameGraphRoot) { + qWarning() << "No active frame graph found"; + return nullptr; + } + + auto surfaceSelector = qobject_cast<Qt3DRender::QRenderSurfaceSelector *>(frameGraphRoot); + if (!surfaceSelector) + surfaceSelector = frameGraphRoot->findChild<Qt3DRender::QRenderSurfaceSelector *>(); + + if (!surfaceSelector) + qWarning() << "No render surface selector found in frame graph"; + + return surfaceSelector; +} + void QRenderSurfaceSelectorPrivate::setExternalRenderTargetSize(const QSize &size) { m_externalRenderTargetSize = size; diff --git a/src/render/framegraph/qrendersurfaceselector_p.h b/src/render/framegraph/qrendersurfaceselector_p.h index d21bf744c..899387b98 100644 --- a/src/render/framegraph/qrendersurfaceselector_p.h +++ b/src/render/framegraph/qrendersurfaceselector_p.h @@ -53,6 +53,7 @@ #include <Qt3DRender/private/qframegraphnode_p.h> #include <Qt3DRender/private/platformsurfacefilter_p.h> +#include <Qt3DRender/private/qt3drender_global_p.h> #include <QtGui/qsurface.h> #include <QtGui/qwindow.h> #include <QtCore/qpointer.h> @@ -61,12 +62,17 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { -class QRenderSurfaceSelectorPrivate : public Qt3DRender::QFrameGraphNodePrivate +class QRenderSurfaceSelector; + +class QT3DRENDERSHARED_PRIVATE_EXPORT QRenderSurfaceSelectorPrivate : public Qt3DRender::QFrameGraphNodePrivate { public: QRenderSurfaceSelectorPrivate(); ~QRenderSurfaceSelectorPrivate(); + // TODO: Qt 5.8, make it public + static QRenderSurfaceSelector *find(QObject *rootObject); + void setExternalRenderTargetSize(const QSize &size); QSize externalRenderTargetSize() const { return m_externalRenderTargetSize; } diff --git a/src/render/framegraph/sortpolicy.cpp b/src/render/framegraph/sortpolicy.cpp index 628fa75e4..9631ebeab 100644 --- a/src/render/framegraph/sortpolicy.cpp +++ b/src/render/framegraph/sortpolicy.cpp @@ -74,6 +74,7 @@ QVector<QSortPolicy::SortType> SortPolicy::sortTypes() const void SortPolicy::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) { + FrameGraphNode::initializeFromPeer(change); const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QSortPolicyData>>(change); const QSortPolicyData &data = typedChange->data; m_sortTypes = data.sortTypes; diff --git a/src/render/framegraph/sortpolicy_p.h b/src/render/framegraph/sortpolicy_p.h index 32d2888c3..868c1430d 100644 --- a/src/render/framegraph/sortpolicy_p.h +++ b/src/render/framegraph/sortpolicy_p.h @@ -60,7 +60,7 @@ namespace Qt3DRender { namespace Render { -class SortPolicy : public FrameGraphNode +class Q_AUTOTEST_EXPORT SortPolicy : public FrameGraphNode { public: SortPolicy(); diff --git a/src/render/frontend/qboundingvolumedebug.cpp b/src/render/frontend/qboundingvolumedebug.cpp deleted file mode 100644 index 4ee6816d6..000000000 --- a/src/render/frontend/qboundingvolumedebug.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 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$ -** -****************************************************************************/ - -#if 0 - -#include "qboundingvolumedebug_p.h" -#include <Qt3DCore/qentity.h> -#include <Qt3DCore/private/qcomponent_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DRender/qspheremesh.h> -#include <Qt3DCore/qtransform.h> -#include <Qt3DRender/qphongalphamaterial.h> -#include <Qt3DRender/qlayer.h> -#include <QThread> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -class QBoundingVolumeDebugPrivate : public Qt3DCore::QComponentPrivate -{ -public: - QBoundingVolumeDebugPrivate() - : QComponentPrivate() - , m_recursive(false) - , m_debugSubtree(nullptr) - , m_sphereMesh(nullptr) - , m_transform(nullptr) - , m_material(nullptr) - , m_layer(nullptr) - , m_bvRadius(0.0f) - { - m_shareable = false; - } - - Q_DECLARE_PUBLIC(QBoundingVolumeDebug) - - bool m_recursive; - Qt3DCore::QEntity *m_debugSubtree; - Qt3DRender::QSphereMesh *m_sphereMesh; - Qt3DCore::QTransform *m_transform; - Qt3DRender::QMaterial *m_material; - Qt3DRender::QLayer *m_layer; - - float m_bvRadius; - QVector3D m_bvCenter; - - Qt3DCore::QEntity *findRootEntity(Qt3DCore::QEntity *e); - void updateSubtree(); -}; - -QBoundingVolumeDebug::QBoundingVolumeDebug(Qt3DCore::QNode *parent) - : QComponent(*new QBoundingVolumeDebugPrivate(), parent) -{ -} - -QBoundingVolumeDebug::~QBoundingVolumeDebug() -{ - QComponent::cleanup(); -} - -void QBoundingVolumeDebug::setRecursive(bool recursive) -{ - Q_D(QBoundingVolumeDebug); - if (d->m_recursive != recursive) { - d->m_recursive = recursive; - emit recursiveChanged(recursive); - } -} - -bool QBoundingVolumeDebug::recursive() const -{ - Q_D(const QBoundingVolumeDebug); - return d->m_recursive; -} - -void QBoundingVolumeDebug::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QBoundingVolumeDebug); - Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); - if (e->type() == Qt3DCore::PropertyUpdated) { - if (e->propertyName() == QByteArrayLiteral("center")) { - d->m_bvCenter = e->value().value<QVector3D>(); - d->updateSubtree(); - } else if (e->propertyName() == QByteArrayLiteral("radius")) { - d->m_bvRadius = e->value().toFloat(); - d->updateSubtree(); - } - } -} - -// Executed in the frontend thread -Qt3DCore::QEntity *QBoundingVolumeDebugPrivate::findRootEntity(Qt3DCore::QEntity *e) -{ - Qt3DCore::QEntity *tmp = nullptr; - Qt3DCore::QEntity *parentEntity = nullptr; - while (e && (tmp = e->parentEntity()) != nullptr) { - parentEntity = tmp; - e = parentEntity; - } - return parentEntity; -} - -void QBoundingVolumeDebugPrivate::updateSubtree() -{ - Q_Q(QBoundingVolumeDebug); - if (m_debugSubtree == nullptr) { - m_debugSubtree = new Qt3DCore::QEntity(); - m_sphereMesh = new Qt3DRender::QSphereMesh(); - m_transform = new Qt3DCore::QTransform(); - m_material = new Qt3DRender::QPhongAlphaMaterial(); - m_layer = new Qt3DRender::QLayer(); - - static_cast<QPhongAlphaMaterial *>(m_material)->setAlpha(0.3f); - static_cast<QPhongAlphaMaterial *>(m_material)->setDiffuse(QColor::fromRgb(255, 153, 0)); - - m_layer->setNames(QStringList() << QStringLiteral("debug")); - - m_debugSubtree->addComponent(m_sphereMesh); - m_debugSubtree->addComponent(m_transform); - m_debugSubtree->addComponent(m_material); - m_debugSubtree->addComponent(m_layer); - - m_transform->setTranslation(m_bvCenter); - m_transform->setScale(m_bvRadius * 2.0f); - m_sphereMesh->setRadius(0.5f); - m_sphereMesh->setRings(100); - m_sphereMesh->setSlices(100); - - // Insert into scene - if (q->entities().size() > 0) { - Qt3DCore::QEntity *rootEntity = findRootEntity(q->entities().constFirst()); - m_debugSubtree->setParent(rootEntity ? rootEntity : q->entities().constFirst()); - } - } else { - // Just update the mesh - m_transform->setTranslation(m_bvCenter); - m_transform->setScale(m_bvRadius * 2.0f); - } -} - -} // Qt3DRender - -QT_END_NAMESPACE - -#endif diff --git a/src/render/frontend/qlayer.cpp b/src/render/frontend/qlayer.cpp index e9f23a015..cd7d92caf 100644 --- a/src/render/frontend/qlayer.cpp +++ b/src/render/frontend/qlayer.cpp @@ -53,7 +53,38 @@ QLayerPrivate::QLayerPrivate() \class Qt3DRender::QLayer \inmodule Qt3DRender \since 5.5 - \brief The QLayer class provides ... + \brief The QLayer class provides a way of filtering which entities will be rendered. + + Qt3DRender::QLayer works in conjunction with the Qt3DRender::QLayerFilter in the FrameGraph. + \sa Qt3DRender::QLayerFilter + + Qt3DRender::QLayer doesn't define any new properties but is supposed to only be referenced. + + \code + #include <Qt3DCore/QEntity> + #include <Qt3DRender/QGeometryRenderer> + #include <Qt3DRender/QLayer> + #include <Qt3DRender/QLayerFilter> + #include <Qt3DRender/QViewport> + + // Scene + Qt3DCore::QEntity *rootEntity = new Qt3DCore::Qt3DCore::QEntity; + + Qt3DCore::QEntity *renderableEntity = new Qt3DCore::Qt3DCore::QEntity(rootEntity); + Qt3DRender::QGeometryRenderer *geometryRenderer = new Qt3DCore::QGeometryRenderer(renderableEntity); + Qt3DRender::QLayer *layer1 = new Qt3DCore::QLayer(renderableEntity); + renderableEntity->addComponent(geometryRenderer); + renderableEntity->addComponent(layer1); + + ... + + // FrameGraph + Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport; + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(viewport); + layerFilter->addLayer(layer1); + + ... + \endcode */ /*! @@ -62,7 +93,48 @@ QLayerPrivate::QLayerPrivate() \inherits Component3D \inqmlmodule Qt3D.Render \since 5.5 - \brief For ... + \sa LayerFilter + \brief Layer provides a way of filtering which entities will be rendered. + + Layer works in conjunction with the LayerFilter in the FrameGraph. + + Layer doesn't define any new properties but is supposed to only be referenced. + + \code + import Qt3D.Core 2.0 + import Qt3D.Render 2.0 + + Entity { + id: root + + components: RenderSettings { + // FrameGraph + Viewport { + ClearBuffers { + buffers: ClearBuffers.ColorDepthBuffer + CameraSelector { + camera: mainCamera + LayerFilter { + layers: [layer1] + } + } + } + } + } + + // Scene + Camera { id: mainCamera } + + Layer { id: layer1 } + + GeometryRenderer { id: mesh } + + Entity { + id: renderableEntity + components: [ mesh, layer1 ] + } + } + \endcode */ /*! \fn Qt3DRender::QLayer::QLayer(Qt3DCore::QNode *parent) diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp index 03a939a13..5a8195b64 100644 --- a/src/render/frontend/qrenderaspect.cpp +++ b/src/render/frontend/qrenderaspect.cpp @@ -77,7 +77,6 @@ #include <Qt3DRender/qrendersurfaceselector.h> #include <Qt3DRender/qrendersettings.h> -#include <Qt3DRender/private/qboundingvolumedebug_p.h> #include <Qt3DRender/private/cameraselectornode_p.h> #include <Qt3DRender/private/layerfilternode_p.h> #include <Qt3DRender/private/filterkey_p.h> @@ -173,6 +172,9 @@ void QRenderAspectPrivate::registerBackendTypes() { Q_Q(QRenderAspect); + qRegisterMetaType<Qt3DRender::QBuffer*>(); + qRegisterMetaType<Qt3DRender::QEffect*>(); + q->registerBackendType<Qt3DCore::QEntity>(QSharedPointer<Render::RenderEntityFunctor>::create(m_renderer, m_nodeManagers)); q->registerBackendType<Qt3DCore::QTransform>(QSharedPointer<Render::NodeFunctor<Render::Transform, Render::TransformManager> >::create(m_renderer, m_nodeManagers->transformManager())); @@ -222,7 +224,6 @@ void QRenderAspectPrivate::registerBackendTypes() q->registerBackendType<QViewport>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::ViewportNode, QViewport> >::create(m_renderer, m_nodeManagers->frameGraphManager())); // Picking - // q->registerBackendType<QBoundingVolumeDebug>(QSharedPointer<Render::NodeFunctor<Render::BoundingVolumeDebug, Render::BoundingVolumeDebugManager> >::create(m_renderer, m_nodeManagers->boundingVolumeDebugManager())); q->registerBackendType<QObjectPicker>(QSharedPointer<Render::NodeFunctor<Render::ObjectPicker, Render::ObjectPickerManager> >::create(m_renderer, m_nodeManagers->objectPickerManager())); } @@ -278,7 +279,6 @@ void QRenderAspectPrivate::unregisterBackendTypes() unregisterBackendType<QViewport>(); // Picking - // unregisterBackendType<QBoundingVolumeDebug>(); unregisterBackendType<QObjectPicker>(); } diff --git a/src/render/frontend/render-frontend.pri b/src/render/frontend/render-frontend.pri index 5f5246518..829e3d756 100644 --- a/src/render/frontend/render-frontend.pri +++ b/src/render/frontend/render-frontend.pri @@ -10,7 +10,6 @@ HEADERS += \ $$PWD/qrendertarget.h \ $$PWD/qrendertarget_p.h \ $$PWD/sphere_p.h \ - $$PWD/qboundingvolumedebug_p.h \ $$PWD/qcamera_p.h \ $$PWD/qcamera.h \ $$PWD/qcameralens.h \ @@ -31,7 +30,6 @@ SOURCES += \ $$PWD/sphere.cpp \ $$PWD/qlayer.cpp \ $$PWD/qrendertarget.cpp \ - $$PWD/qboundingvolumedebug.cpp \ $$PWD/qcamera.cpp \ $$PWD/qcameralens.cpp \ $$PWD/qrendersettings.cpp \ diff --git a/src/render/geometry/qattribute.cpp b/src/render/geometry/qattribute.cpp index 3067b0527..ef439f2b4 100644 --- a/src/render/geometry/qattribute.cpp +++ b/src/render/geometry/qattribute.cpp @@ -65,7 +65,12 @@ QAttributePrivate::QAttributePrivate() * \qmltype Attribute * \instantiates Qt3DRender::QAttribute * \inqmlmodule Qt3D.Render - * \brief Uncreatable + * \brief Defines an attribute and how data should be read from a Buffer. + * + * When providing your own attributes, it may make sense to name your attribute + * using helpers such as QAttribute::defaultPositionAttributeName() as that + * will ensure your geometry will be compatible with picking and the various + * materials provided in the Qt3DExtras module. */ /*! @@ -74,6 +79,14 @@ QAttributePrivate::QAttributePrivate() * * \inherits Qt3DCore::QNode * + * \brief Defines an attribute and how data should be read from a QBuffer. + * + * When providing your own attributes, it may make sense to name your attribute + * using helpers such as QAttribute::defaultPositionAttributeName() as that + * will ensure your geometry will be compatible with picking and the various + * materials provided in the Qt3DExtras module. + * + * \sa QBuffer. */ /*! @@ -119,7 +132,7 @@ QAttribute::QAttribute(QNode *parent) * and \a stride with \a parent. */ QAttribute::QAttribute(QBuffer *buf, VertexBaseType type, uint dataSize, uint count, uint offset, uint stride, QNode *parent) - : QNode(*new QAttributePrivate(), parent) + : QAttribute(parent) { Q_D(QAttribute); setBuffer(buf); @@ -136,7 +149,7 @@ QAttribute::QAttribute(QBuffer *buf, VertexBaseType type, uint dataSize, uint co * dataSize, \a count, \a offset, and \a stride with \a parent. */ QAttribute::QAttribute(QBuffer *buf, const QString &name, VertexBaseType type, uint dataSize, uint count, uint offset, uint stride, QNode *parent) - : QNode(*new QAttributePrivate(), parent) + : QAttribute(parent) { Q_D(QAttribute); setBuffer(buf); diff --git a/src/render/geometry/qbuffer.cpp b/src/render/geometry/qbuffer.cpp index 779f808f7..e63798027 100644 --- a/src/render/geometry/qbuffer.cpp +++ b/src/render/geometry/qbuffer.cpp @@ -59,6 +59,9 @@ QBufferPrivate::QBufferPrivate() * \qmltype Buffer * \instantiates Qt3DRender::QBuffer * \inqmlmodule Qt3D.Render + * + * \brief Provides a data store for raw data to later be used as vertices or + * uniforms. */ /*! @@ -89,6 +92,16 @@ QBufferPrivate::QBufferPrivate() * \inmodule Qt3DRender * * \inherits Qt3DCore::QNode + * + * \brief Provides a data store for raw data to later be used as vertices or + * uniforms. + * + * Data can either be provided directly using QBuffer::setData() or by + * specifying a generator with QBuffer::setDataGenerator() and providing a + * Qt3DRender::QBufferDataGeneratorPtr. + * + * When using a generator the data will be loaded asynchronously in a job. The + * loaded data can be read back if the QBuffer::syncData flag is set to true. */ /*! diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp index 5169c8fb4..acec8edf6 100644 --- a/src/render/graphicshelpers/graphicscontext.cpp +++ b/src/render/graphicshelpers/graphicscontext.cpp @@ -71,6 +71,7 @@ #include <Qt3DRender/private/graphicshelpergl4_p.h> #endif #include <Qt3DRender/private/graphicshelperes2_p.h> +#include <Qt3DRender/private/graphicshelperes3_p.h> #include <QSurface> #include <QWindow> @@ -285,7 +286,6 @@ void GraphicsContext::endDrawing(bool swapBuffers) m_gl->swapBuffers(m_surface); if (m_ownCurrent) m_gl->doneCurrent(); - m_stateSet = nullptr; decayTextureScores(); } @@ -557,7 +557,7 @@ void GraphicsContext::bindFrameBufferAttachmentHelper(GLuint fboId, const Attach if (fboSize.isEmpty()) fboSize = QSize(glTex->width(), glTex->height()); else - fboSize = QSize(qMin(fboSize.width(), glTex->width()), qMin(fboSize.width(), glTex->width())); + fboSize = QSize(qMin(fboSize.width(), glTex->width()), qMin(fboSize.height(), glTex->height())); m_glHelper->bindFrameBufferAttachment(glTex, attachment); } } @@ -647,7 +647,10 @@ GraphicsHelperInterface *GraphicsContext::resolveHighestOpenGLFunctions() GraphicsHelperInterface *glHelper = nullptr; if (m_gl->isOpenGLES()) { - glHelper = new GraphicsHelperES2(); + if (m_gl->format().majorVersion() >= 3) + glHelper = new GraphicsHelperES3(); + else + glHelper = new GraphicsHelperES2(); glHelper->initializeHelper(m_gl, nullptr); qCDebug(Backend) << Q_FUNC_INFO << " Building OpenGL 2/ES2 Helper"; } diff --git a/src/render/graphicshelpers/graphicshelperes2.cpp b/src/render/graphicshelpers/graphicshelperes2.cpp index 6bf287cee..b09e33291 100644 --- a/src/render/graphicshelpers/graphicshelperes2.cpp +++ b/src/render/graphicshelpers/graphicshelperes2.cpp @@ -80,9 +80,6 @@ void GraphicsHelperES2::initializeHelper(QOpenGLContext *context, Q_ASSERT(context); m_funcs = context->functions(); Q_ASSERT(m_funcs); - m_isES3 = context->format().majorVersion() >= 3; - if (m_isES3) - m_extraFuncs = QOpenGLContext::currentContext()->extraFunctions(); } void GraphicsHelperES2::drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, @@ -99,19 +96,11 @@ void GraphicsHelperES2::drawElementsInstancedBaseVertexBaseInstance(GLenum primi if (baseVertex != 0) qWarning() << "glDrawElementsInstancedBaseVertex is not supported with OpenGL ES 2"; - if (m_isES3 && m_extraFuncs) { - m_extraFuncs->glDrawElementsInstanced(primitiveType, - primitiveCount, - indexType, - indices, - instances); - } else { - for (GLint i = 0; i < instances; i++) - drawElements(primitiveType, - primitiveCount, - indexType, - indices); - } + for (GLint i = 0; i < instances; i++) + drawElements(primitiveType, + primitiveCount, + indexType, + indices); } void GraphicsHelperES2::drawArraysInstanced(GLenum primitiveType, @@ -241,8 +230,8 @@ QVector<ShaderStorageBlock> GraphicsHelperES2::programShaderStorageBlocks(GLuint void GraphicsHelperES2::vertexAttribDivisor(GLuint index, GLuint divisor) { - if (m_isES3 && m_extraFuncs) - m_extraFuncs->glVertexAttribDivisor(index, divisor); + Q_UNUSED(index); + Q_UNUSED(divisor); } void GraphicsHelperES2::blendEquation(GLenum mode) @@ -365,7 +354,7 @@ bool GraphicsHelperES2::supportsFeature(GraphicsHelperInterface::Feature feature return false; } } -void GraphicsHelperES2::drawBuffers(GLsizei , const int *) +void GraphicsHelperES2::drawBuffers(GLsizei, const int *) { qWarning() << "drawBuffers is not supported by ES 2.0"; } @@ -462,13 +451,8 @@ void GraphicsHelperES2::bindUniform(const QVariant &v, const ShaderUniform &desc case GL_SAMPLER_CUBE_SHADOW: case GL_SAMPLER_2D_ARRAY: case GL_SAMPLER_2D_ARRAY_SHADOW: - if (m_isES3) { - Q_ASSERT(description.m_size == 1); - m_funcs->glUniform1i(description.m_location, v.toInt()); - } else { - qWarning() << Q_FUNC_INFO << "ES 3.0 uniform type" << description.m_type << "for" - << description.m_name << "is not supported in ES 2.0"; - } + qWarning() << Q_FUNC_INFO << "ES 3.0 uniform type" << description.m_type << "for" + << description.m_name << "is not supported in ES 2.0"; break; default: diff --git a/src/render/graphicshelpers/graphicshelperes2_p.h b/src/render/graphicshelpers/graphicshelperes2_p.h index 5f4413e09..df8f148a9 100644 --- a/src/render/graphicshelpers/graphicshelperes2_p.h +++ b/src/render/graphicshelpers/graphicshelperes2_p.h @@ -118,10 +118,8 @@ public: uint uniformByteSize(const ShaderUniform &description) Q_DECL_OVERRIDE; void useProgram(GLuint programId) Q_DECL_OVERRIDE; void vertexAttribDivisor(GLuint index, GLuint divisor) Q_DECL_OVERRIDE; -private: +protected: QOpenGLFunctions *m_funcs; - QOpenGLExtraFunctions *m_extraFuncs = nullptr; - bool m_isES3; }; } // namespace Render diff --git a/src/render/graphicshelpers/graphicshelperes3.cpp b/src/render/graphicshelpers/graphicshelperes3.cpp new file mode 100644 index 000000000..fe39d9d3f --- /dev/null +++ b/src/render/graphicshelpers/graphicshelperes3.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2016 Svenn-Arne Dragly. +** 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 "graphicshelperes3_p.h" +#include <private/attachmentpack_p.h> +#include <QOpenGLExtraFunctions> + +QT_BEGIN_NAMESPACE + +// ES 3.0+ +#ifndef GL_SAMPLER_3D +#define GL_SAMPLER_3D 0x8B5F +#endif +#ifndef GL_SAMPLER_2D_SHADOW +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#endif +#ifndef GL_SAMPLER_CUBE_SHADOW +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#endif +#ifndef GL_SAMPLER_2D_ARRAY +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#endif +#ifndef GL_SAMPLER_2D_ARRAY_SHADOW +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#endif + +namespace Qt3DRender { +namespace Render { + +GraphicsHelperES3::GraphicsHelperES3() +{ +} + +GraphicsHelperES3::~GraphicsHelperES3() +{ +} + +void GraphicsHelperES3::initializeHelper(QOpenGLContext *context, + QAbstractOpenGLFunctions *functions) +{ + GraphicsHelperES2::initializeHelper(context, functions); + m_extraFuncs = context->extraFunctions(); + Q_ASSERT(m_extraFuncs); +} + +void GraphicsHelperES3::drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, + GLsizei primitiveCount, + GLint indexType, + void *indices, + GLsizei instances, + GLint baseVertex, + GLint baseInstance) +{ + if (baseInstance != 0) + qWarning() << "glDrawElementsInstancedBaseVertexBaseInstance is not supported with OpenGL ES 3"; + + if (baseVertex != 0) + qWarning() << "glDrawElementsInstancedBaseVertex is not supported with OpenGL ES 3"; + + m_extraFuncs->glDrawElementsInstanced(primitiveType, + primitiveCount, + indexType, + indices, + instances); +} + +void GraphicsHelperES3::vertexAttribDivisor(GLuint index, GLuint divisor) +{ + m_extraFuncs->glVertexAttribDivisor(index, divisor); +} + +void GraphicsHelperES3::bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) +{ + GLenum attr = GL_COLOR_ATTACHMENT0; + + if (attachment.m_point <= QRenderTargetOutput::Color15) + attr = GL_COLOR_ATTACHMENT0 + attachment.m_point; + else if (attachment.m_point == QRenderTargetOutput::Depth) + attr = GL_DEPTH_ATTACHMENT; + else if (attachment.m_point == QRenderTargetOutput::Stencil) + attr = GL_STENCIL_ATTACHMENT; + else + qCritical() << "Unsupported FBO attachment OpenGL ES 3.0"; + + texture->bind(); + QOpenGLTexture::Target target = texture->target(); + if (target == QOpenGLTexture::Target2D) + m_funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, attr, target, texture->textureId(), attachment.m_mipLevel); + else if (target == QOpenGLTexture::TargetCubeMap) + m_funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, attr, attachment.m_face, texture->textureId(), attachment.m_mipLevel); + else + qCritical() << "Unsupported Texture FBO attachment format"; + texture->release(); +} + +bool GraphicsHelperES3::supportsFeature(GraphicsHelperInterface::Feature feature) const +{ + switch (feature) { + case RenderBufferDimensionRetrieval: + case MRT: + return true; + default: + return false; + } +} + +void GraphicsHelperES3::drawBuffers(GLsizei n, const int *bufs) +{ + QVarLengthArray<GLenum, 16> drawBufs(n); + + for (int i = 0; i < n; i++) + drawBufs[i] = GL_COLOR_ATTACHMENT0 + bufs[i]; + m_extraFuncs->glDrawBuffers(n, drawBufs.constData()); +} + +void GraphicsHelperES3::bindUniform(const QVariant &v, const ShaderUniform &description) +{ + switch (description.m_type) { + case GL_SAMPLER_3D: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_2D_ARRAY_SHADOW: + Q_ASSERT(description.m_size == 1); + m_funcs->glUniform1i(description.m_location, v.toInt()); + break; + default: + GraphicsHelperES2::bindUniform(v, description); + break; + } +} + +} // namespace Render +} // namespace Qt3DRender + +QT_END_NAMESPACE diff --git a/src/render/frontend/qboundingvolumedebug_p.h b/src/render/graphicshelpers/graphicshelperes3_p.h index 8ffe556b5..e5bb51c53 100644 --- a/src/render/frontend/qboundingvolumedebug_p.h +++ b/src/render/graphicshelpers/graphicshelperes3_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2016 Svenn-Arne Dragly. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt3D module of the Qt Toolkit. @@ -37,10 +38,8 @@ ** ****************************************************************************/ -#if 0 - -#ifndef QT3DRENDER_QBOUNDINGVOLUMEDEBUG_P_H -#define QT3DRENDER_QBOUNDINGVOLUMEDEBUG_P_H +#ifndef QT3DRENDER_RENDER_GRAPHICSHELPERES3_H +#define QT3DRENDER_RENDER_GRAPHICSHELPERES3_H // // W A R N I N G @@ -53,46 +52,34 @@ // We mean it. // -#include <Qt3DCore/qcomponent.h> -#include <Qt3DRender/qt3drender_global.h> +#include <Qt3DRender/private/graphicshelperes2_p.h> QT_BEGIN_NAMESPACE namespace Qt3DRender { +namespace Render { -class QGeometry; -class QBoundingVolumeDebugPrivate; - -class QT3DRENDERSHARED_EXPORT QBoundingVolumeDebug : public Qt3DCore::QComponent +class GraphicsHelperES3 : public GraphicsHelperES2 { - Q_OBJECT - Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged) - public: - explicit QBoundingVolumeDebug(Qt3DCore::QNode *parent = nullptr); - ~QBoundingVolumeDebug(); - - bool recursive() const; - -public Q_SLOTS: - void setRecursive(bool recursive); - -Q_SIGNALS: - void recursiveChanged(bool recursive); - + GraphicsHelperES3(); + virtual ~GraphicsHelperES3(); + + // QGraphicHelperInterface interface + virtual void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) Q_DECL_OVERRIDE; + virtual void bindUniform(const QVariant &v, const ShaderUniform &description) Q_DECL_OVERRIDE; + virtual void drawBuffers(GLsizei n, const int *bufs) Q_DECL_OVERRIDE; + virtual void drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLsizei instances, GLint baseVertex = 0, GLint baseInstance = 0) Q_DECL_OVERRIDE; + virtual void initializeHelper(QOpenGLContext *context, QAbstractOpenGLFunctions *functions) Q_DECL_OVERRIDE; + virtual bool supportsFeature(Feature feature) const Q_DECL_OVERRIDE; + virtual void vertexAttribDivisor(GLuint index, GLuint divisor) Q_DECL_OVERRIDE; protected: - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) Q_DECL_OVERRIDE; - -private: - Q_DECLARE_PRIVATE(QBoundingVolumeDebug) - - // TODO: Handle creation changes + QOpenGLExtraFunctions *m_extraFuncs = Q_NULLPTR; }; -} // Qt3DRender +} // namespace Render +} // namespace Qt3DRender QT_END_NAMESPACE -#endif // QT3DRENDER_QBOUNDINGVOLUMEDEBUG_P_H - -#endif +#endif // QT3DRENDER_RENDER_GRAPHICSHELPERES3_H diff --git a/src/render/graphicshelpers/graphicshelpers.pri b/src/render/graphicshelpers/graphicshelpers.pri index a5dcbe808..ecf2e6b54 100644 --- a/src/render/graphicshelpers/graphicshelpers.pri +++ b/src/render/graphicshelpers/graphicshelpers.pri @@ -6,6 +6,7 @@ HEADERS += \ $$PWD/graphicscontext_p.h \ $$PWD/graphicshelperinterface_p.h \ $$PWD/graphicshelperes2_p.h \ + $$PWD/graphicshelperes3_p.h \ $$PWD/graphicshelpergl2_p.h \ $$PWD/graphicshelpergl3_p.h \ $$PWD/graphicshelpergl3_3_p.h \ @@ -14,6 +15,7 @@ HEADERS += \ SOURCES += \ $$PWD/graphicscontext.cpp \ $$PWD/graphicshelperes2.cpp \ + $$PWD/graphicshelperes3.cpp \ $$PWD/graphicshelpergl2.cpp \ $$PWD/graphicshelpergl3.cpp \ $$PWD/graphicshelpergl3_3.cpp \ diff --git a/src/render/io/qsceneloader.cpp b/src/render/io/qsceneloader.cpp index 215f8edd0..2d0c3311c 100644 --- a/src/render/io/qsceneloader.cpp +++ b/src/render/io/qsceneloader.cpp @@ -67,6 +67,28 @@ QSceneLoaderPrivate::QSceneLoaderPrivate() \brief Provides the facility to load an existing Scene + Given a 3D source file, the Qt3DRender::QSceneLoader will try to parse it and + build a tree of Qt3DCore::QEntity with proper Qt3DRender::QGeometryRenderer + Qt3DCore::QTransform and QtRender::QMaterial components. + + The loader will try to determine the best material to be used based on the properties + of the model file. If you wish to use a custom material, you will have to traverse + the tree and replace the default associated materials with yours. + + As the name implies, Qt3DRender::QSceneLoader loads a complete scene subtree. + If you wish to load a single piece of geometry, you should rather be using + the Qt3DRender::QMesh instead. + + Qt3DRender::QSceneLoader internally relies on the use of plugins to support a + wide variety of 3D file formats. \l + {http://www.assimp.org/main_features_formats.html}{Here} is a list of formats + that are supported by Qt3D. + + \note this component shouldn't be shared among several Qt3DCore::QEntity instances. + Undefined behavior will result. + + \sa Qt3DRender::QMesh + \sa Qt3DRender::QGeometryRenderer */ /*! @@ -76,16 +98,40 @@ QSceneLoaderPrivate::QSceneLoaderPrivate() \inherits Component \since 5.7 \qmlabstract Provides the facility to load an existing Scene + + Given a 3D source file, the SceneLoader will try to parse it and build a + tree of Entity with proper GeometryRenderer, Transform and Material + components. + + The loader will try to determine the best material to be used based on the + properties of the model file. If you wish to use a custom material, you + will have to traverse the tree and replace the default associated materials + with yours. + + As the name implies, SceneLoader loads a complete scene subtree. If you + wish to load a single piece of geometry, you should rather be using the + Mesh instead. + + SceneLoader internally relies on the use of plugins to support a wide + variety of 3D file formats. \l + {http://www.assimp.org/main_features_formats.html}{Here} is a list of + formats that are supported by Qt3D. + + \note this component shouldn't be shared among several Entity instances. + Undefined behavior will result. + + \sa Mesh + \sa GeometryRenderer */ /*! \enum QSceneLoader::Status This enum identifies the state of loading - \value None - \value Loading - \value Ready - \value Error + \value None The Qt3DRender::QSceneLoader hasn't been used yet. + \value Loading The Qt3DRender::QSceneLoader is currently loading the scene file. + \value Ready The Qt3DRender::QSceneLoader successfully loaded the scene file. + \value Error The Qt3DRender::QSceneLoader encountered an error while loading the scene file. */ /*! diff --git a/src/render/jobs/filterlayerentityjob.cpp b/src/render/jobs/filterlayerentityjob.cpp index 5e3536cf2..d22b61337 100644 --- a/src/render/jobs/filterlayerentityjob.cpp +++ b/src/render/jobs/filterlayerentityjob.cpp @@ -93,6 +93,10 @@ void FilterLayerEntityJob::filterLayerAndEntity() for (const HEntity handle : handles) { Entity *entity = entityManager->data(handle); + + if (!entity->isEnabled()) + continue; + const Qt3DCore::QNodeIdVector entityLayers = entity->componentsUuid<Layer>(); // An Entity is positively filtered if it contains at least one Layer component with the same id as the @@ -114,8 +118,11 @@ void FilterLayerEntityJob::selectAllEntities() const QVector<HEntity> handles = entityManager->activeHandles(); m_filteredEntities.reserve(handles.size()); - for (const HEntity handle : handles) - m_filteredEntities.push_back(entityManager->data(handle)); + for (const HEntity handle : handles) { + Entity *e = entityManager->data(handle); + if (e->isEnabled()) + m_filteredEntities.push_back(e); + } } } // Render diff --git a/src/render/jobs/frustumcullingjob_p.h b/src/render/jobs/frustumcullingjob_p.h index 087b7687c..cb4b38b2b 100644 --- a/src/render/jobs/frustumcullingjob_p.h +++ b/src/render/jobs/frustumcullingjob_p.h @@ -62,7 +62,7 @@ namespace Render { class Entity; class EntityManager; -class Plane; +struct Plane; class FrustumCullingJob : public Qt3DCore::QAspectJob { diff --git a/src/render/jobs/loadscenejob.cpp b/src/render/jobs/loadscenejob.cpp index d0d8be9ef..758e0b135 100644 --- a/src/render/jobs/loadscenejob.cpp +++ b/src/render/jobs/loadscenejob.cpp @@ -63,23 +63,29 @@ void LoadSceneJob::run() { // Iterate scene IO handlers until we find one that can handle this file type Qt3DCore::QEntity *sceneSubTree = nullptr; - for (QSceneIOHandler *sceneIOHandler : qAsConst(m_sceneIOHandlers)) { - if (!sceneIOHandler->isFileTypeSupported(m_source)) - continue; - // File type is supported, try to load it - sceneIOHandler->setSource(m_source); - Qt3DCore::QEntity *sub = sceneIOHandler->scene(); - if (sub) { - sceneSubTree = sub; - break; + // Perform the loading only if the source wasn't explicitly set to empty + if (!m_source.isEmpty()) { + for (QSceneIOHandler *sceneIOHandler : qAsConst(m_sceneIOHandlers)) { + if (!sceneIOHandler->isFileTypeSupported(m_source)) + continue; + + // File type is supported, try to load it + sceneIOHandler->setSource(m_source); + Qt3DCore::QEntity *sub = sceneIOHandler->scene(); + if (sub) { + sceneSubTree = sub; + break; + } } } - // Set clone of sceneTree in sceneComponent. This will move the sceneSubTree // to the QCoreApplication thread which is where the frontend object tree lives. Scene *scene = m_managers->sceneManager()->lookupResource(m_sceneComponent); - if (scene && sceneSubTree) + + // If the sceneSubTree is null it will trigger the frontend to unload + // any subtree it may hold + if (scene) scene->setSceneSubtree(sceneSubTree); } diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp index 5c713e1a7..11faf5138 100644 --- a/src/render/jobs/pickboundingvolumejob.cpp +++ b/src/render/jobs/pickboundingvolumejob.cpp @@ -118,6 +118,15 @@ private: return vca; } + bool isUnique(const QVector<ViewportCameraAreaTriplet> &vcaTriplets, const ViewportCameraAreaTriplet &vca) const + { + for (const ViewportCameraAreaTriplet &triplet : vcaTriplets) { + if (vca.cameraId == triplet.cameraId && vca.viewport == triplet.viewport && vca.area == triplet.area) + return false; + } + return true; + } + public: QVector<ViewportCameraAreaTriplet> gather(FrameGraphNode *root) { @@ -129,7 +138,7 @@ public: // Find all viewport/camera pairs by traversing from leaf to root for (Render::FrameGraphNode *leaf : qAsConst(m_leaves)) { ViewportCameraAreaTriplet vcaTriplet = gatherUpViewportCameraAreas(leaf); - if (!vcaTriplet.cameraId.isNull()) + if (!vcaTriplet.cameraId.isNull() && isUnique(vcaTriplets, vcaTriplet)) vcaTriplets.push_back(vcaTriplet); } return vcaTriplets; @@ -519,11 +528,12 @@ void PickBoundingVolumeJob::run() } case QEvent::MouseButtonRelease: { - // Send release event to m_currentPicker - if (lastCurrentPicker != nullptr) { + if (lastCurrentPicker != nullptr && m_currentPicker == objectPickerHandle) m_currentPicker = HObjectPicker(); - lastCurrentPicker->onClicked(pickEvent); - lastCurrentPicker->onReleased(pickEvent); + // Only send the release event if it was pressed + if (objectPicker->isPressed()) { + objectPicker->onClicked(pickEvent); + objectPicker->onReleased(pickEvent); } break; } diff --git a/src/render/jobs/renderviewinitializerjob_p.h b/src/render/jobs/renderviewinitializerjob_p.h index 35620bc65..dbc80c162 100644 --- a/src/render/jobs/renderviewinitializerjob_p.h +++ b/src/render/jobs/renderviewinitializerjob_p.h @@ -54,7 +54,6 @@ #include <Qt3DCore/qaspectjob.h> #include <Qt3DCore/private/qframeallocator_p.h> -#include <QThreadStorage> #include <QSize> QT_BEGIN_NAMESPACE diff --git a/src/render/materialsystem/qgraphicsapifilter.cpp b/src/render/materialsystem/qgraphicsapifilter.cpp index 5a52ff0fd..119a294ac 100644 --- a/src/render/materialsystem/qgraphicsapifilter.cpp +++ b/src/render/materialsystem/qgraphicsapifilter.cpp @@ -55,20 +55,36 @@ GraphicsApiFilterData::GraphicsApiFilterData() bool GraphicsApiFilterData::operator ==(const GraphicsApiFilterData &other) const { - if (other.m_api == m_api - && other.m_profile <= m_profile - && (other.m_major < m_major - || (other.m_major == m_major && other.m_minor <= m_minor))) { - for (const QString &neededExt : other.m_extensions) - if (!m_extensions.contains(neededExt)) - return false; - // If a vendor name was specified in sample, we perform comparison, - // otherwise we assume the vendor name doesn't matter - if (!other.m_vendor.isEmpty()) - return (other.m_vendor == m_vendor); - return true; + // Check API + if (other.m_api != m_api) + return false; + + // Check versions + const bool versionsCompatible = other.m_major < m_major + || (other.m_major == m_major && other.m_minor <= m_minor); + if (!versionsCompatible) + return false; + + // Check profiles if requiring OpenGL (profiles not relevant for OpenGL ES) + if (other.m_api == QGraphicsApiFilter::OpenGL) { + const bool profilesCompatible = m_profile != QGraphicsApiFilter::CoreProfile + || other.m_profile == m_profile; + if (!profilesCompatible) + return false; } - return false; + + // Check extensions + for (const QString &neededExt : other.m_extensions) { + if (!m_extensions.contains(neededExt)) + return false; + } + + // Check vendor + if (!other.m_vendor.isEmpty()) + return (other.m_vendor == m_vendor); + + // If we get here everything looks good :) + return true; } bool GraphicsApiFilterData::operator <(const GraphicsApiFilterData &other) const diff --git a/src/render/materialsystem/qgraphicsapifilter.h b/src/render/materialsystem/qgraphicsapifilter.h index d09c2f753..c618358dd 100644 --- a/src/render/materialsystem/qgraphicsapifilter.h +++ b/src/render/materialsystem/qgraphicsapifilter.h @@ -95,8 +95,8 @@ public Q_SLOTS: void setVendor(const QString &vendor); Q_SIGNALS: - void apiChanged(Api api); - void profileChanged(OpenGLProfile profile); + void apiChanged(Qt3DRender::QGraphicsApiFilter::Api api); + void profileChanged(Qt3DRender::QGraphicsApiFilter::OpenGLProfile profile); void minorVersionChanged(int minorVersion); void majorVersionChanged(int majorVersion); void extensionsChanged(const QStringList &extensions); @@ -107,8 +107,8 @@ private: Q_DECLARE_PRIVATE(QGraphicsApiFilter) }; -bool operator ==(const QGraphicsApiFilter &reference, const QGraphicsApiFilter &sample); -bool operator !=(const QGraphicsApiFilter &reference, const QGraphicsApiFilter &sample); +Q_AUTOTEST_EXPORT bool operator ==(const QGraphicsApiFilter &reference, const QGraphicsApiFilter &sample); +Q_AUTOTEST_EXPORT bool operator !=(const QGraphicsApiFilter &reference, const QGraphicsApiFilter &sample); } // namespace Qt3DRender diff --git a/src/render/picking/qobjectpicker.cpp b/src/render/picking/qobjectpicker.cpp index 29912fa79..1842b7fee 100644 --- a/src/render/picking/qobjectpicker.cpp +++ b/src/render/picking/qobjectpicker.cpp @@ -313,7 +313,7 @@ void QObjectPickerPrivate::propagateEvent(QPickEvent *event, EventType type) if (!m_entities.isEmpty()) { Qt3DCore::QEntity *entity = m_entities.first(); Qt3DCore::QEntity *parentEntity = nullptr; - while (entity != nullptr && entity->parent() != nullptr && !event->isAccepted()) { + while (entity != nullptr && entity->parentEntity() != nullptr && !event->isAccepted()) { parentEntity = entity->parentEntity(); const auto components = parentEntity->components(); for (Qt3DCore::QComponent *c : components) { diff --git a/src/render/renderstates/renderstatenode.cpp b/src/render/renderstates/renderstatenode.cpp index 47e82a9bd..d1698e4b6 100644 --- a/src/render/renderstates/renderstatenode.cpp +++ b/src/render/renderstates/renderstatenode.cpp @@ -63,7 +63,7 @@ void RenderStateNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBaseP { cleanup(); const auto renderStateChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChangeBase>(change); - m_impl = std::move(RenderStateSet::initializeStateFromPeer(renderStateChange)); + m_impl = RenderStateSet::initializeStateFromPeer(renderStateChange); } void RenderStateNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) diff --git a/src/render/renderstates/renderstateset.cpp b/src/render/renderstates/renderstateset.cpp index ffe7f6ee8..992d649e8 100644 --- a/src/render/renderstates/renderstateset.cpp +++ b/src/render/renderstates/renderstateset.cpp @@ -94,7 +94,6 @@ namespace Render { RenderStateSet::RenderStateSet() : m_stateMask(0) - , m_cachedPrevious(0) { } @@ -153,24 +152,15 @@ void RenderStateSet::apply(GraphicsContext *gc) } qCDebug(RenderStates) << " current states " << QString::number(stateMask(), 2) << "inverse " << QString::number(invOurState, 2) << " -> states to change: " << QString::number(stateToReset, 2); + // Reset states that aren't active in the current state set resetMasked(stateToReset, gc); - if (m_cachedPrevious && previousStates == m_cachedPrevious) { - // state-change cache hit - for (const StateVariant &ds : qAsConst(m_cachedDeltaStates)) - ds.apply(gc); - } else { - // compute deltas and cache for next frame - m_cachedDeltaStates.clear(); - m_cachedPrevious = previousStates; - - for (const StateVariant &ds : qAsConst(m_states)) { - if (previousStates && previousStates->contains(ds)) - continue; - - m_cachedDeltaStates.push_back(ds); - ds.apply(gc); - } + // Apply states that weren't in the previous state or that have + // different values + for (const StateVariant &ds : qAsConst(m_states)) { + if (previousStates && previousStates->contains(ds)) + continue; + ds.apply(gc); } } diff --git a/src/render/renderstates/renderstateset_p.h b/src/render/renderstates/renderstateset_p.h index 96af97f84..307e0ff1d 100644 --- a/src/render/renderstates/renderstateset_p.h +++ b/src/render/renderstates/renderstateset_p.h @@ -114,9 +114,7 @@ private: bool contains(const StateVariant &ds) const; StateMaskSet m_stateMask; - RenderStateSet* m_cachedPrevious; QVector<StateVariant> m_states; - QVector<StateVariant> m_cachedDeltaStates; }; template<> diff --git a/src/render/renderstates/statevariant.cpp b/src/render/renderstates/statevariant.cpp index 7a47d429e..f472d9920 100644 --- a/src/render/renderstates/statevariant.cpp +++ b/src/render/renderstates/statevariant.cpp @@ -79,7 +79,7 @@ void StateVariant::apply(GraphicsContext *gc) const data.scissorTest.apply(gc); return; case StencilTestStateMask: - data.scissorTest.apply(gc); + data.stencilTest.apply(gc); return; case AlphaCoverageStateMask: data.alphaCoverage.apply(gc); diff --git a/src/render/texture/qtexture.cpp b/src/render/texture/qtexture.cpp index 09ace37d0..13e6a04ab 100644 --- a/src/render/texture/qtexture.cpp +++ b/src/render/texture/qtexture.cpp @@ -954,6 +954,7 @@ bool QTextureFromSourceGenerator::operator ==(const QTextureGenerator &other) co QTextureFromSourceGenerator::QTextureFromSourceGenerator(const QUrl &url) : QTextureGenerator() , m_url(url) + , m_status(QAbstractTexture::None) { } diff --git a/src/render/texture/qtextureimage.cpp b/src/render/texture/qtextureimage.cpp index cc8d7acfe..dab92082a 100644 --- a/src/render/texture/qtextureimage.cpp +++ b/src/render/texture/qtextureimage.cpp @@ -170,6 +170,7 @@ void QTextureImage::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) QImageTextureDataFunctor::QImageTextureDataFunctor(const QUrl &url) : QTextureImageDataGenerator() , m_url(url) + , m_status(QTextureImage::None) { if (url.isLocalFile()) { QFileInfo info(url.toLocalFile()); |