From b830f4307559007ff1b9c91bed6a881a6f6efdfb Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Mon, 30 Jul 2018 14:13:10 +0200 Subject: Document third party asset 'miramar' The files got added in commit f49cabe35cbd. However, the original sources from the linked url are in .tga format, so I assume they got converted before importing. We should probably add a 'Modifications' entry to highlight such conversions in the future. https://opengameart.org/content/miramar-skybox categorises the license as CC-BY 3.0, but the upload was done not by the author. Change-Id: I312a871716104507434eb6d12a547c3752da51af Reviewed-by: Paul Lemire --- .../assets/cubemaps/miramar/qt_attribution.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 examples/qt3d/exampleresources/assets/cubemaps/miramar/qt_attribution.json diff --git a/examples/qt3d/exampleresources/assets/cubemaps/miramar/qt_attribution.json b/examples/qt3d/exampleresources/assets/cubemaps/miramar/qt_attribution.json new file mode 100644 index 000000000..6eccf001c --- /dev/null +++ b/examples/qt3d/exampleresources/assets/cubemaps/miramar/qt_attribution.json @@ -0,0 +1,14 @@ +{ + "Id": "miramar-sky", + "Name": "Miramar Skybox Textures", + "QDocModule": "qt3d", + "QtUsage": "Used in the anaglyph-rendering example and autotests of Qt 3D.", + + "QtParts": [ "examples", "tests" ] , + "Description": "High res environment map (converted to webgl).", + "Homepage": "http://www.zfight.com/misc/files/textures/envmap_miramar.rar", + "DownloadLocation": "https://opengameart.org/sites/default/files/envmap_miramar.zip", + "License": "Modify however you like, just cred me for my work, maybe link to my page.", + "LicenseFile": "README.txt", + "Copyright": "Copyright (c) Jockum Skoglund aka hipshot" +} -- cgit v1.2.3 From e22971073ee10ee891c61a94f934b0b3403cc5a7 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 21 Sep 2018 15:33:34 +0200 Subject: GLTexture: mark texture for upload when it's recreated and contains data In some cases, a GLTexture will destroy its internal OpenGL texture before recreating it (when it requires a new allocation due to some property change). When this happens, we need to ensure we also request our content data to be uploaded after the new internal OpenGL texture is recreated. Change-Id: Ifd3f8a1e40e5fad63d117417006c65fade5c2b39 Task-number: QTBUG-70551 Reviewed-by: Sean Harmer --- src/render/renderers/opengl/textures/gltexture.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/render/renderers/opengl/textures/gltexture.cpp b/src/render/renderers/opengl/textures/gltexture.cpp index b61d06a80..e98f3965d 100644 --- a/src/render/renderers/opengl/textures/gltexture.cpp +++ b/src/render/renderers/opengl/textures/gltexture.cpp @@ -212,6 +212,10 @@ GLTexture::TextureUpdateInfo GLTexture::createOrUpdateGLTexture() delete m_gl; m_gl = nullptr; textureInfo.wasUpdated = true; + // If we are destroyed because of some property change but still our content data + // make sure we are marked for upload + if (m_textureData || !m_imageData.empty()) + needUpload = true; } -- cgit v1.2.3 From e879254613469b1b5290fca31ea69cb6ea407c06 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Mon, 24 Sep 2018 09:29:10 +0200 Subject: QText2DEntity: clear glyphrun when scene changes GlyphRun stores a reference to glyphs and indirectly to a suitable TextureAtlas based on the font needed by the glyphs. Whenever we recompute the glyph because some property has changed we: 1) Store information about the glyph we need 2) Generate a Rendering Entity for the glyph we need 3) Dereference the glyphs we don't need anymore (the old glyph run) Step 3) is performed last as whenever no more glyph reference a TextureAtlas, it gets deleted. If we were to do that first, we could end up in cases where we destroy the atlas and recreate it just after because the new GlyphRun actually uses the same font. TextureAtlases are tied to the lifetime of the scene's root node. However if the scene changes, the previous glyph run wouldn't be released. Since we don't keep a direct relationship between Glyphs and TextureAtlas (we basically do a getOrCreateTextureAtlasForFont and lookup available atlases in the scene), we could actually end up destroying a texture atlas we still need the next time we update our glyph run: When deferencing the old glyphs (whose texture atlas has been destroyed when the scene has changed), we would instead be removing references to the new atlas required by the new nodes (if they share the same font). To fix that, whenever the scene changes, we now clear the glyph run as well. Change-Id: Ibe62e2f6438c6655d2997681117c341302d64799 Task-number: QTBUG-70551 Reviewed-by: Sean Harmer --- src/extras/text/qtext2dentity.cpp | 15 ++++++++++++++- src/extras/text/qtext2dentity_p.h | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/extras/text/qtext2dentity.cpp b/src/extras/text/qtext2dentity.cpp index 10939a1e2..ae25e8ecc 100644 --- a/src/extras/text/qtext2dentity.cpp +++ b/src/extras/text/qtext2dentity.cpp @@ -92,10 +92,17 @@ void QText2DEntityPrivate::setScene(Qt3DCore::QScene *scene) // Unref old glyph cache if it exists if (m_scene != nullptr) { + // Ensure we don't keep reference to glyphs + // if we are changing the cache + if (m_glyphCache != nullptr) + clearCurrentGlyphRuns(); + m_glyphCache = nullptr; + QText2DEntityPrivate::CacheEntry &entry = QText2DEntityPrivate::m_glyphCacheInstances[m_scene]; --entry.count; if (entry.count == 0 && entry.glyphCache != nullptr) { + delete entry.glyphCache; entry.glyphCache = nullptr; } @@ -149,7 +156,6 @@ void QText2DEntityPrivate::setCurrentGlyphRuns(const QVector &runs) // For each distinct texture, we need a separate DistanceFieldTextRenderer, // for which we need vertex and index data QHash renderData; - const float scale = computeActualScale(); // process glyph runs @@ -248,6 +254,13 @@ void QText2DEntityPrivate::setCurrentGlyphRuns(const QVector &runs) m_currentGlyphRuns = runs; } +void QText2DEntityPrivate::clearCurrentGlyphRuns() +{ + for (int i = 0; i < m_currentGlyphRuns.size(); i++) + m_glyphCache->derefGlyphs(m_currentGlyphRuns[i]); + m_currentGlyphRuns.clear(); +} + void QText2DEntityPrivate::update() { if (m_glyphCache == nullptr) diff --git a/src/extras/text/qtext2dentity_p.h b/src/extras/text/qtext2dentity_p.h index 934e2087f..b98c62ce3 100644 --- a/src/extras/text/qtext2dentity_p.h +++ b/src/extras/text/qtext2dentity_p.h @@ -104,6 +104,7 @@ public: float computeActualScale() const; void setCurrentGlyphRuns(const QVector &runs); + void clearCurrentGlyphRuns(); void update(); struct CacheEntry -- cgit v1.2.3 From 999424908f17fa543baace39eb76a3c0ac89c7b5 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Mon, 24 Sep 2018 18:05:06 +0200 Subject: Doc: Mark deprecated Qt 3D QML types obsolete The types will be listed on the "Obsolete QML Types" page that is linked from the "All QML Types" page. Task-number: QTBUG-69713 Change-Id: Ieff402d1cce426c0ce4b9191b8fe9b1dd02b4328 Reviewed-by: Mats Honkamaa Reviewed-by: Miikka Heikkinen --- src/doc/src/qmlextramaterials.qdoc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/doc/src/qmlextramaterials.qdoc b/src/doc/src/qmlextramaterials.qdoc index 10198845f..c54cc948b 100644 --- a/src/doc/src/qmlextramaterials.qdoc +++ b/src/doc/src/qmlextramaterials.qdoc @@ -28,6 +28,8 @@ /*! \qmltype DiffuseMapMaterial \inqmlmodule Qt3D.Extras + \obsolete + \brief The DiffuseMapMaterial provides a default implementation of the phong lighting effect where the diffuse light component is read from a texture map. \since 5.7 @@ -86,6 +88,8 @@ /*! \qmltype DiffuseSpecularMapMaterial \inqmlmodule Qt3D.Extras + \obsolete + \brief The DiffuseSpecularMapMaterial provides a default implementation of the phong lighting effect where the diffuse and specular light components are read from texture maps. \since 5.7 @@ -220,6 +224,8 @@ /*! \qmltype NormalDiffuseMapAlphaMaterial \inqmlmodule Qt3D.Extras + \obsolete + \brief The NormalDiffuseMapAlphaMaterial provides a specialization of NormalDiffuseMapMaterial with alpha coverage and a depth test performed in the rendering pass. \since 5.7 @@ -291,6 +297,8 @@ /*! \qmltype NormalDiffuseMapMaterial \inqmlmodule Qt3D.Extras + \obsolete + \brief The NormalDiffuseMapMaterial provides a default implementation of the phong lighting and bump effect where the diffuse light component is read from a texture map and the normals of the mesh being rendered from a normal texture map. @@ -363,6 +371,8 @@ /*! \qmltype NormalDiffuseSpecularMapMaterial \inqmlmodule Qt3D.Extras + \obsolete + \brief The NormalDiffuseSpecularMapMaterial provides a default implementation of the phong lighting and bump effect where the diffuse and specular light components are read from texture maps and the normals of the mesh being rendered from a normal texture map. @@ -465,6 +475,8 @@ /*! \qmltype PhongAlphaMaterial \inqmlmodule Qt3D.Extras + \obsolete + \brief The PhongAlphaMaterial class provides a default implementation of the phong lighting effect with alpha. \since 5.7 @@ -516,6 +528,8 @@ /*! \qmltype PhongMaterial \inqmlmodule Qt3D.Extras + \obsolete + \brief The PhongMaterial class provides a default implementation of the phong lighting effect. \since 5.7 \inherits Qt3D.Render::Material -- cgit v1.2.3 From 74b8191968184bf94f14409be77566a2730de89e Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Wed, 26 Sep 2018 09:11:17 +0200 Subject: QOrbitCameraController: make zoom work when pressing shift key Was mistakenly using yAxis instead of zAxis input value. Change-Id: Id91d04565c503ae5f286f6b433e246a1b94d6e12 Reviewed-by: Mike Krus --- src/extras/defaults/qorbitcameracontroller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extras/defaults/qorbitcameracontroller.cpp b/src/extras/defaults/qorbitcameracontroller.cpp index 6d3e83bcb..aff91f6cf 100644 --- a/src/extras/defaults/qorbitcameracontroller.cpp +++ b/src/extras/defaults/qorbitcameracontroller.cpp @@ -186,7 +186,7 @@ void QOrbitCameraController::moveCamera(const QAbstractCameraController::InputSt } else if (state.shiftKeyActive) { if (zoomDistance(camera()->position(), theCamera->viewCenter()) > d->m_zoomInLimit * d->m_zoomInLimit) { // Dolly - theCamera->translate(QVector3D(0, 0, state.tyAxisValue * linearSpeed() * dt), theCamera->DontTranslateViewCenter); + theCamera->translate(QVector3D(0, 0, state.tzAxisValue * linearSpeed() * dt), theCamera->DontTranslateViewCenter); } else { theCamera->translate(QVector3D(0, 0, -0.5), theCamera->DontTranslateViewCenter); } -- cgit v1.2.3 From 565a89ac4303f31b091eba05174e9724355fb747 Mon Sep 17 00:00:00 2001 From: Michael Dippold Date: Sun, 23 Sep 2018 23:51:37 -0700 Subject: Scene3D crashing on destruction Moved logic accessing the Scene3DItem from the render function into an afterSynchronization call which has the main thread locked to prevent the race condition. Task-number: QTBUG-70747 Change-Id: I596d445512b5985c7dfb54d228fa0a5fcc596a27 Reviewed-by: Paul Lemire --- src/quick3d/imports/scene3d/scene3ditem.cpp | 3 -- src/quick3d/imports/scene3d/scene3drenderer.cpp | 58 +++++++++++++------------ src/quick3d/imports/scene3d/scene3drenderer_p.h | 1 + 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/quick3d/imports/scene3d/scene3ditem.cpp b/src/quick3d/imports/scene3d/scene3ditem.cpp index 2f791b202..ddb25777c 100644 --- a/src/quick3d/imports/scene3d/scene3ditem.cpp +++ b/src/quick3d/imports/scene3d/scene3ditem.cpp @@ -372,9 +372,6 @@ QSGNode *Scene3DItem::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNode m_renderer->setCleanerHelper(m_rendererCleaner); } - // The main thread is blocked, it is now time to sync data between the renderer and the item. - m_renderer->synchronize(); - Scene3DSGNode *fboNode = static_cast(node); if (fboNode == nullptr) { fboNode = new Scene3DSGNode(); diff --git a/src/quick3d/imports/scene3d/scene3drenderer.cpp b/src/quick3d/imports/scene3d/scene3drenderer.cpp index b3cac0dcd..b96fc516d 100644 --- a/src/quick3d/imports/scene3d/scene3drenderer.cpp +++ b/src/quick3d/imports/scene3d/scene3drenderer.cpp @@ -138,11 +138,13 @@ Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *asp , m_lastMultisample(false) , m_needsShutdown(true) , m_blocking(false) + , m_forceRecreate(false) { Q_CHECK_PTR(m_item); Q_CHECK_PTR(m_item->window()); m_window = m_item->window(); + QObject::connect(m_item->window(), &QQuickWindow::afterSynchronizing, this, &Scene3DRenderer::synchronize, Qt::DirectConnection); QObject::connect(m_item->window(), &QQuickWindow::beforeRendering, this, &Scene3DRenderer::render, Qt::DirectConnection); QObject::connect(m_item->window(), &QQuickWindow::sceneGraphInvalidated, this, &Scene3DRenderer::onSceneGraphInvalidated, Qt::DirectConnection); // So that we can schedule the cleanup @@ -247,7 +249,30 @@ void Scene3DRenderer::onWindowChanged(QQuickWindow *w) void Scene3DRenderer::synchronize() { - m_multisample = m_item->multisample(); + if (m_item && m_window) { + m_multisample = m_item->multisample(); + + if (m_aspectEngine->rootEntity() != m_item->entity()) { + scheduleRootEntityChange(); + } + + const QSize boundingRectSize = m_item->boundingRect().size().toSize(); + const QSize currentSize = boundingRectSize * m_window->effectiveDevicePixelRatio(); + const bool sizeHasChanged = currentSize != m_lastSize; + const bool multisampleHasChanged = m_multisample != m_lastMultisample; + m_forceRecreate = sizeHasChanged || multisampleHasChanged; + + if (sizeHasChanged) { + static const QMetaMethod setItemAreaAndDevicePixelRatio = setItemAreaAndDevicePixelRatioMethod(); + setItemAreaAndDevicePixelRatio.invoke(m_item, Qt::QueuedConnection, Q_ARG(QSize, boundingRectSize), + Q_ARG(qreal, m_window->effectiveDevicePixelRatio())); + } + + // Store the current size as a comparison + // point for the next frame + m_lastSize = currentSize; + m_lastMultisample = m_multisample; + } } void Scene3DRenderer::setSGNode(Scene3DSGNode *node) @@ -261,51 +286,30 @@ void Scene3DRenderer::render() { QMutexLocker l(&m_windowMutex); // Lock to ensure the window doesn't change while we are rendering - if (!m_item || !m_window) + if (!m_window) return; - if (m_aspectEngine->rootEntity() != m_item->entity()) - scheduleRootEntityChange(); - ContextSaver saver; // The OpenGL state may be dirty from the previous QtQuick nodes, so reset // it here to give Qt3D the clean state it expects m_window->resetOpenGLState(); - const QSize boundingRectSize = m_item->boundingRect().size().toSize(); - const QSize currentSize = boundingRectSize * m_window->effectiveDevicePixelRatio(); - const bool sizeHasChanged = currentSize != m_lastSize; - const bool multisampleHasChanged = m_multisample != m_lastMultisample; - const bool forceRecreate = sizeHasChanged || multisampleHasChanged; - - if (sizeHasChanged) { - // We are in the QSGRenderThread (doing a direct call would result in a race) - static const QMetaMethod setItemAreaAndDevicePixelRatio = setItemAreaAndDevicePixelRatioMethod(); - setItemAreaAndDevicePixelRatio.invoke(m_item, Qt::QueuedConnection, Q_ARG(QSize, boundingRectSize), - Q_ARG(qreal, m_window->effectiveDevicePixelRatio())); - } - // Rebuild FBO and textures if never created or a resize has occurred - if ((m_multisampledFBO.isNull() || forceRecreate) && m_multisample) { - m_multisampledFBO.reset(createMultisampledFramebufferObject(currentSize)); + if ((m_multisampledFBO.isNull() || m_forceRecreate) && m_multisample) { + m_multisampledFBO.reset(createMultisampledFramebufferObject(m_lastSize)); if (m_multisampledFBO->format().samples() == 0 || !QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { m_multisample = false; m_multisampledFBO.reset(nullptr); } } - if (m_finalFBO.isNull() || forceRecreate) { - m_finalFBO.reset(createFramebufferObject(currentSize)); + if (m_finalFBO.isNull() || m_forceRecreate) { + m_finalFBO.reset(createFramebufferObject(m_lastSize)); m_texture.reset(m_window->createTextureFromId(m_finalFBO->texture(), m_finalFBO->size(), QQuickWindow::TextureHasAlphaChannel)); m_node->setTexture(m_texture.data()); } - // Store the current size as a comparison - // point for the next frame - m_lastSize = currentSize; - m_lastMultisample = m_multisample; - // Bind FBO if (m_multisample) //Only try to use MSAA when available m_multisampledFBO->bind(); diff --git a/src/quick3d/imports/scene3d/scene3drenderer_p.h b/src/quick3d/imports/scene3d/scene3drenderer_p.h index eb2b930ef..e28ecbe6e 100644 --- a/src/quick3d/imports/scene3d/scene3drenderer_p.h +++ b/src/quick3d/imports/scene3d/scene3drenderer_p.h @@ -110,6 +110,7 @@ private: bool m_lastMultisample; bool m_needsShutdown; bool m_blocking; + bool m_forceRecreate; friend class Scene3DCleaner; }; -- cgit v1.2.3 From 6eb906bf5770370a8a5c15568d9f9463863e53a4 Mon Sep 17 00:00:00 2001 From: Mauro Persano Date: Sat, 22 Sep 2018 09:55:52 -0300 Subject: Use GLSL texture() instead of texture2D() on ES3 Change-Id: Icfec19e5bd76f6a6ca53700a5a3705aa97763859 Reviewed-by: Paul Lemire --- src/render/materialsystem/prototypes/default.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/render/materialsystem/prototypes/default.json b/src/render/materialsystem/prototypes/default.json index 535f144d7..0b971f456 100644 --- a/src/render/materialsystem/prototypes/default.json +++ b/src/render/materialsystem/prototypes/default.json @@ -85,6 +85,15 @@ "substitution": "highp vec4 $color = texture2D($name, $coord);", "headerSnippets": [ "uniform sampler2D $name;" ] }, + { + "format": { + "api": "OpenGLES", + "major": 3, + "minor": 0 + }, + "substitution": "highp vec4 $color = texture($name, $coord);", + "headerSnippets": [ "uniform sampler2D $name;" ] + }, { "format": { "api": "OpenGLCoreProfile", -- cgit v1.2.3 From dbaf2319dace853ae6c0badd7f46c7631961ad09 Mon Sep 17 00:00:00 2001 From: Mauro Persano Date: Sat, 22 Sep 2018 10:02:01 -0300 Subject: ES3 deprecated gl_FragColor, use output variable instead Change-Id: I9a6a7ee88db5471a1c4ed88ed13c99d66b764d93 Reviewed-by: Paul Lemire --- src/render/materialsystem/prototypes/default.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/render/materialsystem/prototypes/default.json b/src/render/materialsystem/prototypes/default.json index 0b971f456..7f196c8df 100644 --- a/src/render/materialsystem/prototypes/default.json +++ b/src/render/materialsystem/prototypes/default.json @@ -118,6 +118,15 @@ }, "substitution": "gl_FragColor = $fragColor;" }, + { + "format": { + "api": "OpenGLES", + "major": 3, + "minor": 0 + }, + "substitution": "fragColor = $fragColor;", + "headerSnippets": [ "out highp vec4 fragColor;" ] + }, { "format": { "api": "OpenGLCoreProfile", -- cgit v1.2.3 From c8e95f84095f3627a6b63ef66751525616c96d5d Mon Sep 17 00:00:00 2001 From: Mauro Persano Date: Sat, 22 Sep 2018 10:11:09 -0300 Subject: Add metalRoughFunction to ES3 Change-Id: I5ac330462bf051285dafbfa4554aa97e6657ac65 Reviewed-by: Mike Krus Reviewed-by: Paul Lemire --- src/extras/extras.qrc | 3 + src/extras/shaders/es3/default.vert | 82 +++++ src/extras/shaders/es3/light.inc.frag | 25 ++ src/extras/shaders/es3/metalrough.inc.frag | 348 ++++++++++++++++++++++ src/render/materialsystem/prototypes/default.json | 9 + 5 files changed, 467 insertions(+) create mode 100644 src/extras/shaders/es3/default.vert create mode 100644 src/extras/shaders/es3/light.inc.frag create mode 100644 src/extras/shaders/es3/metalrough.inc.frag diff --git a/src/extras/extras.qrc b/src/extras/extras.qrc index bfb14f3f9..8bbffd272 100644 --- a/src/extras/extras.qrc +++ b/src/extras/extras.qrc @@ -5,14 +5,17 @@ shaders/gl3/light.inc.frag shaders/es2/light.inc.frag shaders/es2/light.inc.frag100 + shaders/es3/light.inc.frag shaders/gl3/phong.inc.frag shaders/es2/phong.inc.frag shaders/es2/phong.inc.frag100 shaders/gl3/metalrough.inc.frag + shaders/es3/metalrough.inc.frag shaders/gl3/coordinatesystems.inc shaders/es2/coordinatesystems.inc shaders/gl3/default.vert shaders/es2/default.vert + shaders/es3/default.vert shaders/gl3/pervertexcolor.frag shaders/gl3/pervertexcolor.vert shaders/es2/pervertexcolor.frag diff --git a/src/extras/shaders/es3/default.vert b/src/extras/shaders/es3/default.vert new file mode 100644 index 000000000..7641882f2 --- /dev/null +++ b/src/extras/shaders/es3/default.vert @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#version 300 es + +in vec3 vertexPosition; +in vec3 vertexNormal; +in vec4 vertexTangent; +in vec2 vertexTexCoord; + +out vec3 worldPosition; +out vec3 worldNormal; +out vec4 worldTangent; +out vec2 texCoord; + +uniform mat4 modelMatrix; +uniform mat3 modelNormalMatrix; +uniform mat4 modelViewProjection; + +uniform float texCoordScale; + +void main() +{ + // Pass through scaled texture coordinates + texCoord = vertexTexCoord * texCoordScale; + + // Transform position, normal, and tangent to world space + worldPosition = vec3(modelMatrix * vec4(vertexPosition, 1.0)); + worldNormal = normalize(modelNormalMatrix * vertexNormal); + worldTangent.xyz = normalize(vec3(modelMatrix * vec4(vertexTangent.xyz, 0.0))); + worldTangent.w = vertexTangent.w; + + // Calculate vertex position in clip coordinates + gl_Position = modelViewProjection * vec4(vertexPosition, 1.0); +} diff --git a/src/extras/shaders/es3/light.inc.frag b/src/extras/shaders/es3/light.inc.frag new file mode 100644 index 000000000..9d03fca54 --- /dev/null +++ b/src/extras/shaders/es3/light.inc.frag @@ -0,0 +1,25 @@ +const int MAX_LIGHTS = 8; +const int TYPE_POINT = 0; +const int TYPE_DIRECTIONAL = 1; +const int TYPE_SPOT = 2; +struct Light { + int type; + vec3 position; + vec3 color; + float intensity; + vec3 direction; + float constantAttenuation; + float linearAttenuation; + float quadraticAttenuation; + float cutOffAngle; +}; +uniform Light lights[MAX_LIGHTS]; +uniform int lightCount; + +// Pre-convolved environment maps +struct EnvironmentLight { + highp samplerCube irradiance; // For diffuse contribution + highp samplerCube specular; // For specular contribution +}; +uniform EnvironmentLight envLight; +uniform int envLightCount; diff --git a/src/extras/shaders/es3/metalrough.inc.frag b/src/extras/shaders/es3/metalrough.inc.frag new file mode 100644 index 000000000..85f392f4c --- /dev/null +++ b/src/extras/shaders/es3/metalrough.inc.frag @@ -0,0 +1,348 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +precision highp float; + +// Exposure correction +uniform float exposure; +// Gamma correction +const float gamma = 2.2; + +#pragma include light.inc.frag + +int mipLevelCount(const in samplerCube cube) +{ + int baseSize = textureSize(cube, 0).x; + int nMips = int(log2(float(baseSize > 0 ? baseSize : 1))) + 1; + return nMips; +} + +float remapRoughness(const in float roughness) +{ + // As per page 14 of + // http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf + // we remap the roughness to give a more perceptually linear response + // of "bluriness" as a function of the roughness specified by the user. + // r = roughness^2 + const float maxSpecPower = 999999.0; + const float minRoughness = sqrt(2.0 / (maxSpecPower + 2.0)); + return max(roughness * roughness, minRoughness); +} + +float alphaToMipLevel(float alpha) +{ + float specPower = 2.0 / (alpha * alpha) - 2.0; + + // We use the mip level calculation from Lys' default power drop, which in + // turn is a slight modification of that used in Marmoset Toolbag. See + // https://docs.knaldtech.com/doku.php?id=specular_lys for details. + // For now we assume a max specular power of 999999 which gives + // maxGlossiness = 1. + const float k0 = 0.00098; + const float k1 = 0.9921; + float glossiness = (pow(2.0, -10.0 / sqrt(specPower)) - k0) / k1; + + // TODO: Optimize by doing this on CPU and set as + // uniform int envLight.specularMipLevels say (if present in shader). + // Lookup the number of mips in the specular envmap + int mipLevels = mipLevelCount(envLight.specular); + + // Offset of smallest miplevel we should use (corresponds to specular + // power of 1). I.e. in the 32x32 sized mip. + const float mipOffset = 5.0; + + // The final factor is really 1 - g / g_max but as mentioned above g_max + // is 1 by definition here so we can avoid the division. If we make the + // max specular power for the spec map configurable, this will need to + // be handled properly. + float mipLevel = (float(mipLevels) - 1.0 - mipOffset) * (1.0 - glossiness); + return mipLevel; +} + +float normalDistribution(const in vec3 n, const in vec3 h, const in float alpha) +{ + // Blinn-Phong approximation - see + // http://graphicrants.blogspot.co.uk/2013/08/specular-brdf-reference.html + float specPower = 2.0 / (alpha * alpha) - 2.0; + return (specPower + 2.0) / (2.0 * 3.14159) * pow(max(dot(n, h), 0.0), specPower); +} + +vec3 fresnelFactor(const in vec3 color, const in float cosineFactor) +{ + // Calculate the Fresnel effect value + vec3 f = color; + vec3 F = f + (1.0 - f) * pow(1.0 - cosineFactor, 5.0); + return clamp(F, f, vec3(1.0)); +} + +float geometricModel(const in float lDotN, + const in float vDotN, + const in vec3 h) +{ + // Implicit geometric model (equal to denominator in specular model). + // This currently assumes that there is no attenuation by geometric shadowing or + // masking according to the microfacet theory. + return lDotN * vDotN; +} + +vec3 specularModel(const in vec3 F0, + const in float sDotH, + const in float sDotN, + const in float vDotN, + const in vec3 n, + const in vec3 h) +{ + // Clamp sDotN and vDotN to small positive value to prevent the + // denominator in the reflection equation going to infinity. Balance this + // by using the clamped values in the geometric factor function to + // avoid ugly seams in the specular lighting. + float sDotNPrime = max(sDotN, 0.001); + float vDotNPrime = max(vDotN, 0.001); + + vec3 F = fresnelFactor(F0, sDotH); + float G = geometricModel(sDotNPrime, vDotNPrime, h); + + vec3 cSpec = F * G / (4.0 * sDotNPrime * vDotNPrime); + return clamp(cSpec, vec3(0.0), vec3(1.0)); +} + +vec3 pbrModel(const in int lightIndex, + const in vec3 wPosition, + const in vec3 wNormal, + const in vec3 wView, + const in vec3 baseColor, + const in float metalness, + const in float alpha, + const in float ambientOcclusion) +{ + // Calculate some useful quantities + vec3 n = wNormal; + vec3 s = vec3(0.0); + vec3 v = wView; + vec3 h = vec3(0.0); + + float vDotN = dot(v, n); + float sDotN = 0.0; + float sDotH = 0.0; + float att = 1.0; + + if (lights[lightIndex].type != TYPE_DIRECTIONAL) { + // Point and Spot lights + vec3 sUnnormalized = vec3(lights[lightIndex].position) - wPosition; + s = normalize(sUnnormalized); + + // Calculate the attenuation factor + sDotN = dot(s, n); + if (sDotN > 0.0) { + if (lights[lightIndex].constantAttenuation != 0.0 + || lights[lightIndex].linearAttenuation != 0.0 + || lights[lightIndex].quadraticAttenuation != 0.0) { + float dist = length(sUnnormalized); + att = 1.0 / (lights[lightIndex].constantAttenuation + + lights[lightIndex].linearAttenuation * dist + + lights[lightIndex].quadraticAttenuation * dist * dist); + } + + // The light direction is in world space already + if (lights[lightIndex].type == TYPE_SPOT) { + // Check if fragment is inside or outside of the spot light cone + if (degrees(acos(dot(-s, lights[lightIndex].direction))) > lights[lightIndex].cutOffAngle) + sDotN = 0.0; + } + } + } else { + // Directional lights + // The light direction is in world space already + s = normalize(-lights[lightIndex].direction); + sDotN = dot(s, n); + } + + h = normalize(s + v); + sDotH = dot(s, h); + + // Calculate diffuse component + vec3 diffuseColor = (1.0 - metalness) * baseColor * lights[lightIndex].color; + vec3 diffuse = diffuseColor * max(sDotN, 0.0) / 3.14159; + + // Calculate specular component + vec3 dielectricColor = vec3(0.04); + vec3 F0 = mix(dielectricColor, baseColor, metalness); + vec3 specularFactor = vec3(0.0); + if (sDotN > 0.0) { + specularFactor = specularModel(F0, sDotH, sDotN, vDotN, n, h); + specularFactor *= normalDistribution(n, h, alpha); + } + vec3 specularColor = lights[lightIndex].color; + vec3 specular = specularColor * specularFactor; + + // Blend between diffuse and specular to conserver energy + vec3 color = att * lights[lightIndex].intensity * (specular + diffuse * (vec3(1.0) - specular)); + + // Reduce by ambient occlusion amount + color *= ambientOcclusion; + + return color; +} + +vec3 pbrIblModel(const in vec3 wNormal, + const in vec3 wView, + const in vec3 baseColor, + const in float metalness, + const in float alpha, + const in float ambientOcclusion) +{ + // Calculate reflection direction of view vector about surface normal + // vector in world space. This is used in the fragment shader to sample + // from the environment textures for a light source. This is equivalent + // to the l vector for punctual light sources. Armed with this, calculate + // the usual factors needed + vec3 n = wNormal; + vec3 l = reflect(-wView, n); + vec3 v = wView; + vec3 h = normalize(l + v); + float vDotN = dot(v, n); + float lDotN = dot(l, n); + float lDotH = dot(l, h); + + // Calculate diffuse component + vec3 diffuseColor = (1.0 - metalness) * baseColor; + vec3 diffuse = diffuseColor * texture(envLight.irradiance, l).rgb; + + // Calculate specular component + vec3 dielectricColor = vec3(0.04); + vec3 F0 = mix(dielectricColor, baseColor, metalness); + vec3 specularFactor = specularModel(F0, lDotH, lDotN, vDotN, n, h); + + float lod = alphaToMipLevel(alpha); +//#define DEBUG_SPECULAR_LODS +#ifdef DEBUG_SPECULAR_LODS + if (lod > 7.0) + return vec3(1.0, 0.0, 0.0); + else if (lod > 6.0) + return vec3(1.0, 0.333, 0.0); + else if (lod > 5.0) + return vec3(1.0, 1.0, 0.0); + else if (lod > 4.0) + return vec3(0.666, 1.0, 0.0); + else if (lod > 3.0) + return vec3(0.0, 1.0, 0.666); + else if (lod > 2.0) + return vec3(0.0, 0.666, 1.0); + else if (lod > 1.0) + return vec3(0.0, 0.0, 1.0); + else if (lod > 0.0) + return vec3(1.0, 0.0, 1.0); +#endif + vec3 specularSkyColor = textureLod(envLight.specular, l, lod).rgb; + vec3 specular = specularSkyColor * specularFactor; + + // Blend between diffuse and specular to conserve energy + vec3 color = specular + diffuse * (vec3(1.0) - specularFactor); + + // Reduce by ambient occlusion amount + color *= ambientOcclusion; + + return color; +} + +vec3 toneMap(const in vec3 c) +{ + return c / (c + vec3(1.0)); +} + +vec3 gammaCorrect(const in vec3 color) +{ + return pow(color, vec3(1.0 / gamma)); +} + +vec4 metalRoughFunction(const in vec4 baseColor, + const in float metalness, + const in float roughness, + const in float ambientOcclusion, + const in vec3 worldPosition, + const in vec3 worldView, + const in vec3 worldNormal) +{ + vec3 cLinear = vec3(0.0); + + // Remap roughness for a perceptually more linear correspondence + float alpha = remapRoughness(roughness); + + for (int i = 0; i < envLightCount; ++i) { + cLinear += pbrIblModel(worldNormal, + worldView, + baseColor.rgb, + metalness, + alpha, + ambientOcclusion); + } + + for (int i = 0; i < lightCount; ++i) { + cLinear += pbrModel(i, + worldPosition, + worldNormal, + worldView, + baseColor.rgb, + metalness, + alpha, + ambientOcclusion); + } + + // Apply exposure correction + cLinear *= pow(2.0, exposure); + + // Apply simple (Reinhard) tonemap transform to get into LDR range [0, 1] + vec3 cToneMapped = toneMap(cLinear); + + // Apply gamma correction prior to display + vec3 cGamma = gammaCorrect(cToneMapped); + + return vec4(cGamma, 1.0); +} diff --git a/src/render/materialsystem/prototypes/default.json b/src/render/materialsystem/prototypes/default.json index 7f196c8df..63c39164c 100644 --- a/src/render/materialsystem/prototypes/default.json +++ b/src/render/materialsystem/prototypes/default.json @@ -461,6 +461,15 @@ "outputColor" ], "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 3, + "minor": 0 + }, + "substitution": "highp vec4 $outputColor = metalRoughFunction($baseColor, $metalness, $roughness, $ambientOcclusion, $worldPosition, $worldView, $worldNormal);", + "headerSnippets": [ "#pragma include :/shaders/es3/metalrough.inc.frag" ] + }, { "format": { "api": "OpenGLCoreProfile", -- cgit v1.2.3 From d05d2fd3d2fdc24604748a57ce26d48972457058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A4=C3=A4tt=C3=A4=20Antti?= Date: Tue, 25 Sep 2018 11:04:08 +0300 Subject: Fix QMorphPhongMaterial Replace the removed phong.frag with graph-based fragment shader. Task-number: QTBUG-69751 Change-Id: I196be25aff656d6934d6179e4f082430b109b2a1 Reviewed-by: Paul Lemire --- src/extras/defaults/qmorphphongmaterial.cpp | 26 ++++++++++++++++++++------ src/extras/defaults/qmorphphongmaterial_p.h | 3 +++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/extras/defaults/qmorphphongmaterial.cpp b/src/extras/defaults/qmorphphongmaterial.cpp index ade9f8542..1711a21dd 100644 --- a/src/extras/defaults/qmorphphongmaterial.cpp +++ b/src/extras/defaults/qmorphphongmaterial.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -57,9 +58,9 @@ namespace Qt3DExtras { QMorphPhongMaterialPrivate::QMorphPhongMaterialPrivate() : QMaterialPrivate() , m_phongEffect(new QEffect()) - , m_ambientParameter(new QParameter(QStringLiteral("ka"), QColor::fromRgbF(0.05f, 0.05f, 0.05f, 1.0f))) - , m_diffuseParameter(new QParameter(QStringLiteral("kd"), QColor::fromRgbF(0.7f, 0.7f, 0.7f, 1.0f))) - , m_specularParameter(new QParameter(QStringLiteral("ks"), QColor::fromRgbF(0.01f, 0.01f, 0.01f, 1.0f))) + , m_ambientParameter(new QParameter(QStringLiteral("ka"), QColor::fromRgbF(0.05, 0.05, 0.05, 1.0))) + , m_diffuseParameter(new QParameter(QStringLiteral("kd"), QColor::fromRgbF(0.7, 0.7, 0.7, 1.0))) + , m_specularParameter(new QParameter(QStringLiteral("ks"), QColor::fromRgbF(0.01, 0.01, 0.01, 1.0))) , m_shininessParameter(new QParameter(QStringLiteral("shininess"), 150.0f)) , m_interpolatorParameter(new QParameter(QStringLiteral("interpolator"), 0.0f)) , m_phongGL3Technique(new QTechnique()) @@ -70,12 +71,16 @@ QMorphPhongMaterialPrivate::QMorphPhongMaterialPrivate() , m_phongES2RenderPass(new QRenderPass()) , m_phongGL3Shader(new QShaderProgram()) , m_phongGL2ES2Shader(new QShaderProgram()) + , m_phongGL3ShaderBuilder(new QShaderProgramBuilder()) + , m_phongGL2ES2ShaderBuilder(new QShaderProgramBuilder()) , m_filterKey(new QFilterKey) { } void QMorphPhongMaterialPrivate::init() { + Q_Q(QMorphPhongMaterial); + connect(m_ambientParameter, &Qt3DRender::QParameter::valueChanged, this, &QMorphPhongMaterialPrivate::handleAmbientChanged); connect(m_diffuseParameter, &Qt3DRender::QParameter::valueChanged, @@ -88,9 +93,19 @@ void QMorphPhongMaterialPrivate::init() this, &QMorphPhongMaterialPrivate::handleInterpolatorChanged); m_phongGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/morphphong.vert")))); - m_phongGL3Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/phong.frag")))); + m_phongGL3ShaderBuilder->setParent(q); + m_phongGL3ShaderBuilder->setShaderProgram(m_phongGL3Shader); + m_phongGL3ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json"))); + m_phongGL3ShaderBuilder->setEnabledLayers({QStringLiteral("diffuse"), + QStringLiteral("specular"), + QStringLiteral("normal")}); m_phongGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/morphphong.vert")))); - m_phongGL2ES2Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/phong.frag")))); + m_phongGL2ES2ShaderBuilder->setParent(q); + m_phongGL2ES2ShaderBuilder->setShaderProgram(m_phongGL2ES2Shader); + m_phongGL2ES2ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json"))); + m_phongGL2ES2ShaderBuilder->setEnabledLayers({QStringLiteral("diffuse"), + QStringLiteral("specular"), + QStringLiteral("normal")}); m_phongGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL); m_phongGL3Technique->graphicsApiFilter()->setMajorVersion(3); @@ -115,7 +130,6 @@ void QMorphPhongMaterialPrivate::init() m_phongGL2Technique->addRenderPass(m_phongGL2RenderPass); m_phongES2Technique->addRenderPass(m_phongES2RenderPass); - Q_Q(QMorphPhongMaterial); m_filterKey->setParent(q); m_filterKey->setName(QStringLiteral("renderingStyle")); m_filterKey->setValue(QStringLiteral("forward")); diff --git a/src/extras/defaults/qmorphphongmaterial_p.h b/src/extras/defaults/qmorphphongmaterial_p.h index 25bff9042..28b7750d9 100644 --- a/src/extras/defaults/qmorphphongmaterial_p.h +++ b/src/extras/defaults/qmorphphongmaterial_p.h @@ -60,6 +60,7 @@ class QTechnique; class QParameter; class QShaderProgram; class QRenderPass; +class QShaderProgramBuilder; } // namespace Qt3DRender @@ -94,6 +95,8 @@ public: Qt3DRender::QRenderPass *m_phongES2RenderPass; Qt3DRender::QShaderProgram *m_phongGL3Shader; Qt3DRender::QShaderProgram *m_phongGL2ES2Shader; + Qt3DRender::QShaderProgramBuilder *m_phongGL3ShaderBuilder; + Qt3DRender::QShaderProgramBuilder *m_phongGL2ES2ShaderBuilder; Qt3DRender::QFilterKey *m_filterKey; Q_DECLARE_PUBLIC(QMorphPhongMaterial) -- cgit v1.2.3 From 9b51fea01cc6b44c6ba49eda6a75cd92d9388689 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 2 Oct 2018 09:47:42 +0200 Subject: Remove unused CameraController.qml from simple-qml example Change-Id: Id76f8fc4d4701933e7744ff0dff837ec5e4bcc02 Reviewed-by: Sean Harmer --- examples/qt3d/simple-qml/CameraController.qml | 297 ----------------------- examples/qt3d/simple-qml/doc/src/simple-qml.qdoc | 16 -- examples/qt3d/simple-qml/simple-qml.qrc | 1 - 3 files changed, 314 deletions(-) delete mode 100644 examples/qt3d/simple-qml/CameraController.qml diff --git a/examples/qt3d/simple-qml/CameraController.qml b/examples/qt3d/simple-qml/CameraController.qml deleted file mode 100644 index 69eff70ed..000000000 --- a/examples/qt3d/simple-qml/CameraController.qml +++ /dev/null @@ -1,297 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Paul Lemire -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** 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. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import Qt3D.Core 2.0 -import Qt3D.Render 2.0 -import Qt3D.Input 2.0 -import Qt3D.Logic 2.0 -import QtQml 2.2 - -Entity { - id: root - property Camera camera - property real linearSpeed: 10.0 - property real orbitSpeed: -180.0 - property real lookSpeed: 180.0 - property bool firstPersonMode: true - - QtObject { - id: d - readonly property vector3d firstPersonUp: Qt.vector3d(0, 1, 0) - property bool leftMouseButtonPressed: false - property bool rightMouseButtonPressed: false - property real vx: 0; - property real vy: 0; - property real vz: 0; - property real dx: 0 - property real dy: 0 - property bool fineMotion: false - } - - KeyboardDevice { - id: keyboardSourceDevice - } - - MouseDevice { - id: mouseSourceDevice - sensitivity: d.fineMotion ? 0.01 : 0.1 - } - - LogicalDevice { - id: cameraControlDevice - - actions: [ - Action { - name: "LMB" - inputs: [ - ActionInput { - sourceDevice: mouseSourceDevice - buttons: [MouseEvent.LeftButton] - } - ] - }, - Action { - name: "RMB" - inputs: [ - ActionInput { - sourceDevice: mouseSourceDevice - buttons: [MouseEvent.RightButton] - } - ] - }, - Action { - name: "fineMotion" - inputs: [ - ActionInput { - sourceDevice: keyboardSourceDevice - buttons: [Qt.Key_Shift] - } - ] - } - - ] // actions - - axes: [ - // Rotation - Axis { - name: "RX" - inputs: [ - AnalogAxisInput { - sourceDevice: mouseSourceDevice - axis: MouseDevice.X - } - ] - }, - Axis { - name: "RY" - inputs: [ - AnalogAxisInput { - sourceDevice: mouseSourceDevice - axis: MouseDevice.Y - } - ] - }, - // Translation - Axis { - name: "TX" - inputs: [ - ButtonAxisInput { - sourceDevice: keyboardSourceDevice - buttons: [Qt.Key_Left] - scale: -1.0 - }, - ButtonAxisInput { - sourceDevice: keyboardSourceDevice - buttons: [Qt.Key_Right] - scale: 1.0 - } - ] - }, - Axis { - name: "TZ" - inputs: [ - ButtonAxisInput { - sourceDevice: keyboardSourceDevice - buttons: [Qt.Key_Up] - scale: 1.0 - }, - ButtonAxisInput { - sourceDevice: keyboardSourceDevice - buttons: [Qt.Key_Down] - scale: -1.0 - } - ] - }, - Axis { - name: "TY" - inputs: [ - ButtonAxisInput { - sourceDevice: keyboardSourceDevice - buttons: [Qt.Key_PageUp] - scale: 1.0 - }, - ButtonAxisInput { - sourceDevice: keyboardSourceDevice - buttons: [Qt.Key_PageDown] - scale: -1.0 - } - ] - } - ] // axes - } - - components: [ - AxisActionHandler { - id: handler - logicalDevice: cameraControlDevice - - onAxisValueChanged: { - - switch (name) { - - case "TX": { - d.vx = axisValue * linearSpeed - break; - } - - case "TY": { - d.vy = axisValue * linearSpeed - break; - } - - case "TZ": { - d.vz = axisValue * linearSpeed - break; - } - - case "RX": { - d.dx = axisValue; - break; - } - - case "RY": { - d.dy = axisValue; - break; - } - - } - } - - onActionStarted: { - - switch (name) { - - case "LMB": { - d.leftMouseButtonPressed = true; - break; - } - - case "RMB": { - d.rightMouseButtonPressed = true; - break; - } - - case "fineMotion": { - console.log("fineMotion started") - d.fineMotion = true; - break; - } - - } - - } - - onActionFinished: { - - switch (name) { - - case "LMB": { - d.leftMouseButtonPressed = false; - break; - } - - case "RMB": { - d.rightMouseButtonPressed = false; - break; - } - - case "fineMotion": { - console.log("fineMotion finished") - d.fineMotion = false; - break; - } - - } - } - }, - - FrameAction { - onTriggered: { - // The time difference since the last frame is passed in as the - // argument dt. It is a floating point value in units of seconds. - root.camera.translate(Qt.vector3d(d.vx, d.vy, d.vz).times(dt)) - - if (d.leftMouseButtonPressed) { - if (root.firstPersonMode) - root.camera.pan(root.lookSpeed * d.dx * dt, d.firstPersonUp) - else - root.camera.pan(root.lookSpeed * d.dx * dt) - root.camera.tilt(root.lookSpeed * d.dy * dt) - } else if (d.rightMouseButtonPressed) { - if (root.firstPersonMode) - root.camera.panAboutViewCenter(root.lookSpeed * d.dx * dt, d.firstPersonUp) - else - root.camera.panAboutViewCenter(root.lookSpeed * d.dx * dt) - root.camera.tiltAboutViewCenter(root.orbitSpeed * d.dy * dt) - } - } - } - ] // components -} diff --git a/examples/qt3d/simple-qml/doc/src/simple-qml.qdoc b/examples/qt3d/simple-qml/doc/src/simple-qml.qdoc index 13ca8ff1f..9d4f55c52 100644 --- a/examples/qt3d/simple-qml/doc/src/simple-qml.qdoc +++ b/examples/qt3d/simple-qml/doc/src/simple-qml.qdoc @@ -65,20 +65,4 @@ \skipto InputSettings \printuntil } - - \section1 - - \section1 Specifying Settings and Axes - - In the \e CameraController.qml file, we use the LogicalDevice type to define - a set of actions and axes to use within the application: - - \quotefromfile simple-qml/CameraController.qml - \skipto LogicalDevice { - \printuntil ] - \dots - \skipto axes - \printuntil ] - \dots - \skipto /^\}/ */ diff --git a/examples/qt3d/simple-qml/simple-qml.qrc b/examples/qt3d/simple-qml/simple-qml.qrc index 9d95d9835..5f6483ac3 100644 --- a/examples/qt3d/simple-qml/simple-qml.qrc +++ b/examples/qt3d/simple-qml/simple-qml.qrc @@ -1,6 +1,5 @@ main.qml - CameraController.qml -- cgit v1.2.3 From c19036f8484e0ce08e4f38b7e0bd0d64772ded67 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Tue, 2 Oct 2018 15:40:43 +0200 Subject: QChangeArbiter: fix leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When all observers for a node have been removed, we should also remove its entry in m_nodeObservations hash. Change-Id: I56762bb345e6a3eba74d5174b225dc86acd17e8f Task-number: QTBUG-70892 Reviewed-by: Juan José Casafranca Reviewed-by: Sean Harmer --- src/core/qchangearbiter.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/core/qchangearbiter.cpp b/src/core/qchangearbiter.cpp index d6c7e05df..2e32d6722 100644 --- a/src/core/qchangearbiter.cpp +++ b/src/core/qchangearbiter.cpp @@ -217,12 +217,15 @@ void QChangeArbiter::registerSceneObserver(QSceneObserverInterface *observer) void QChangeArbiter::unregisterObserver(QObserverInterface *observer, QNodeId nodeId) { QMutexLocker locker(&m_mutex); - if (m_nodeObservations.contains(nodeId)) { - QObserverList &observers = m_nodeObservations[nodeId]; + const auto it = m_nodeObservations.find(nodeId); + if (it != m_nodeObservations.end()) { + QObserverList &observers = it.value(); for (int i = observers.count() - 1; i >= 0; i--) { if (observers[i].second == observer) observers.removeAt(i); } + if (observers.isEmpty()) + m_nodeObservations.erase(it); } } -- cgit v1.2.3 From ff07ec93db2b56fb3c3047549a1ad7c7d0e367e8 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Wed, 3 Oct 2018 08:46:28 +0200 Subject: Fix leak with VAOManager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I09f15de230c571adb580bdbb3250405f562f255b Task-number: QTBUG-70892 Reviewed-by: Juan José Casafranca Reviewed-by: Sean Harmer --- src/render/renderers/opengl/renderer/openglvertexarrayobject.cpp | 5 +++++ src/render/renderers/opengl/renderer/openglvertexarrayobject_p.h | 1 + src/render/renderers/opengl/renderer/renderer.cpp | 3 ++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/render/renderers/opengl/renderer/openglvertexarrayobject.cpp b/src/render/renderers/opengl/renderer/openglvertexarrayobject.cpp index 0c4fd8c9d..f5d0a64f5 100644 --- a/src/render/renderers/opengl/renderer/openglvertexarrayobject.cpp +++ b/src/render/renderers/opengl/renderer/openglvertexarrayobject.cpp @@ -108,6 +108,11 @@ void OpenGLVertexArrayObject::create(SubmissionContext *ctx, const VAOIdentifier m_owners = key; } +VAOIdentifier OpenGLVertexArrayObject::key() const +{ + return m_owners; +} + // called from Render thread void OpenGLVertexArrayObject::destroy() { diff --git a/src/render/renderers/opengl/renderer/openglvertexarrayobject_p.h b/src/render/renderers/opengl/renderer/openglvertexarrayobject_p.h index eee837221..4896df9bf 100644 --- a/src/render/renderers/opengl/renderer/openglvertexarrayobject_p.h +++ b/src/render/renderers/opengl/renderer/openglvertexarrayobject_p.h @@ -73,6 +73,7 @@ public: void release(); void create(SubmissionContext *ctx, const VAOIdentifier &key); + VAOIdentifier key() const; void destroy(); void cleanup(); diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp index 7319fd0e5..e1d237622 100644 --- a/src/render/renderers/opengl/renderer/renderer.cpp +++ b/src/render/renderers/opengl/renderer/renderer.cpp @@ -2142,7 +2142,8 @@ void Renderer::cleanGraphicsResources() OpenGLVertexArrayObject *vao = m_nodesManager->vaoManager()->data(vaoHandle); if (vao) { vao->destroy(); - m_nodesManager->vaoManager()->release(vaoHandle); + // We remove VAO from manager using its VAOIdentifier + m_nodesManager->vaoManager()->releaseResource(vao->key()); } } } -- cgit v1.2.3 From 08f979f96f454fb407a86b939d48c66dc354d623 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Thu, 4 Oct 2018 10:20:02 +0200 Subject: Further complete missing functions on ES3 helpers Change-Id: I62e83c360619a2e096401330a61a6f2602b743d2 Task-number: QTBUG-70660 Reviewed-by: Sean Harmer --- .../renderers/opengl/graphicshelpers/graphicshelperes3.cpp | 8 ++++++++ .../opengl/graphicshelpers/graphicshelperes3_2.cpp | 13 +++++++++++++ .../opengl/graphicshelpers/graphicshelperes3_2_p.h | 1 + .../renderers/opengl/graphicshelpers/graphicshelperes3_p.h | 1 + 4 files changed, 23 insertions(+) diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3.cpp b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3.cpp index 29ecf9308..34c1e7448 100644 --- a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3.cpp +++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3.cpp @@ -234,6 +234,14 @@ void GraphicsHelperES3::vertexAttributePointer(GLenum shaderDataType, } } +void GraphicsHelperES3::drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances) +{ + m_extraFuncs->glDrawArraysInstanced(primitiveType, + first, + count, + instances); +} + void GraphicsHelperES3::readBuffer(GLenum mode) { m_extraFuncs->glReadBuffer(mode); diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2.cpp b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2.cpp index 9dce08e4f..56da249f2 100644 --- a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2.cpp +++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2.cpp @@ -117,6 +117,19 @@ void GraphicsHelperES3_2::setVerticesPerPatch(GLint verticesPerPatch) m_extraFuncs->glPatchParameteri(GL_PATCH_VERTICES, verticesPerPatch); } +void GraphicsHelperES3_2::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 2"; + + m_extraFuncs->glDrawElementsInstancedBaseVertex(primitiveType, + primitiveCount, + indexType, + indices, + instances, + baseVertex); +} + } // namespace Render } // namespace Qt3DRender diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2_p.h index ed71b1e3e..259864379 100644 --- a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2_p.h +++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2_p.h @@ -70,6 +70,7 @@ public: void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) override; bool frameBufferNeedsRenderBuffer(const Attachment &attachment) override; void setVerticesPerPatch(GLint verticesPerPatch) override; + void drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLsizei instances, GLint baseVertex = 0, GLint baseInstance = 0) override; }; } // namespace Render diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_p.h index 142b7cadd..d4467cf7f 100644 --- a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_p.h +++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_p.h @@ -74,6 +74,7 @@ public: void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) override; void buildUniformBuffer(const QVariant &v, const ShaderUniform &description, QByteArray &buffer) override; void drawBuffers(GLsizei n, const int *bufs) override; + void drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances) override; void drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLsizei instances, GLint baseVertex = 0, GLint baseInstance = 0) override; void readBuffer(GLenum mode) override; void drawBuffer(GLenum mode) override; -- cgit v1.2.3 From c82d0c81aa109667a3fcef8637d25fc6ef6f6059 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 5 Oct 2018 08:14:08 +0200 Subject: Fix compilation with -qt3d-profile-jobs on Android Change-Id: Id6dc461bbc61712f59484898c54a85d07fd8fc22 Reviewed-by: Mike Krus --- src/core/jobs/qthreadpooler.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/jobs/qthreadpooler.cpp b/src/core/jobs/qthreadpooler.cpp index 6819faca7..ca123ddad 100644 --- a/src/core/jobs/qthreadpooler.cpp +++ b/src/core/jobs/qthreadpooler.cpp @@ -41,6 +41,11 @@ #include #if QT_CONFIG(qt3d_profile_jobs) + +#ifdef Q_OS_ANDROID +#include +#endif + #include #include #include -- cgit v1.2.3 From d8789d8fd17fd58f06003e9846b3d107ffc8ec52 Mon Sep 17 00:00:00 2001 From: Joni Poikelin Date: Fri, 5 Oct 2018 11:29:15 +0300 Subject: Fix normal calculation in MorphPhongMaterial MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Iad160f2d454633b558bee91b1e01c287d4202451 Reviewed-by: Antti Määttä --- src/extras/shaders/es2/morphphong.vert | 2 +- src/extras/shaders/gl3/morphphong.vert | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/extras/shaders/es2/morphphong.vert b/src/extras/shaders/es2/morphphong.vert index d091e87c0..89877dca8 100644 --- a/src/extras/shaders/es2/morphphong.vert +++ b/src/extras/shaders/es2/morphphong.vert @@ -25,7 +25,7 @@ void main() morphNormal = normalize(vertexNormal + vertexNormalTarget * abs(interpolator)); } - worldNormal = normalize( modelNormalMatrix * morphPos ); + worldNormal = normalize( modelNormalMatrix * morphNormal ); worldPosition = vec3( modelMatrix * vec4( morphPos, 1.0 ) ); gl_Position = modelViewProjection * vec4( morphPos, 1.0 ); diff --git a/src/extras/shaders/gl3/morphphong.vert b/src/extras/shaders/gl3/morphphong.vert index c74fbdcff..7a8bdd097 100644 --- a/src/extras/shaders/gl3/morphphong.vert +++ b/src/extras/shaders/gl3/morphphong.vert @@ -27,7 +27,7 @@ void main() morphNormal = normalize(vertexNormal + vertexNormalTarget * abs(interpolator)); } - worldNormal = normalize( modelNormalMatrix * morphPos ); + worldNormal = normalize( modelNormalMatrix * morphNormal ); worldPosition = vec3( modelMatrix * vec4( morphPos, 1.0 ) ); gl_Position = modelViewProjection * vec4( morphPos, 1.0 ); -- cgit v1.2.3