diff --git a/src/quick3d/qquick3ditem2d.cpp b/src/quick3d/qquick3ditem2d.cpp
index 3650f1d870d85ded9db8e6ad137b514373bd592a..74edc3f0c648a9cc75700be67995448d1be4c227 100644
--- a/src/quick3d/qquick3ditem2d.cpp
+++ b/src/quick3d/qquick3ditem2d.cpp
@@ -179,11 +179,12 @@ QSSGRenderGraphObject *QQuick3DItem2D::updateSpatialNode(QSSGRenderGraphObject *
 
     m_layer->setSize(textureSize);
 
-    itemNode->qsgTexture = m_layer;
+    itemNode->zOrder = float(m_sourceItem->z());
     if (m_sourceItem->isVisible())
         itemNode->combinedOpacity = itemNode->globalOpacity * float(m_sourceItem->opacity());
     else
         itemNode->combinedOpacity = 0.0f;
+    itemNode->qsgTexture = m_layer;
 
     return node;
 }
diff --git a/src/runtimerender/graphobjects/qssgrenderitem2d_p.h b/src/runtimerender/graphobjects/qssgrenderitem2d_p.h
index 39e25f1e8a797a706de0558a9da0e3701f0d5632..258da7b682cd39a0dee8ddaaba47a71b167f704a 100644
--- a/src/runtimerender/graphobjects/qssgrenderitem2d_p.h
+++ b/src/runtimerender/graphobjects/qssgrenderitem2d_p.h
@@ -54,7 +54,8 @@ struct Q_QUICK3DRUNTIMERENDER_EXPORT QSSGRenderItem2D : public QSSGRenderNode
 
     QSGTexture *qsgTexture = nullptr;
     QMatrix4x4 MVP;
-    float combinedOpacity;
+    float combinedOpacity = 1.0;
+    float zOrder = 0;
 
     QSSGRenderItem2D();
     ~QSSGRenderItem2D();
diff --git a/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderdata.cpp b/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderdata.cpp
index 01d16069247f5970986dee232adbe8ce7339c1ae..be2eb648167140914e3b6e5b8ac2a5ab992cbefe 100644
--- a/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderdata.cpp
+++ b/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderdata.cpp
@@ -839,6 +839,22 @@ void QSSGLayerRenderData::runRenderPass(TRenderRenderableFunction inRenderFn,
         inRenderFn(*this, *theObject, theCameraProps, getShaderFeatureSet(), indexLight, inCamera);
     }
 
+    // Render Quick items
+    for (auto theNodeEntry : getRenderableItem2Ds()) {
+        QSSGRenderItem2D *item2D = static_cast<QSSGRenderItem2D *>(theNodeEntry.node);
+        // Fast-path to avoid rendering totally transparent items
+        if (item2D->combinedOpacity < QSSG_RENDER_MINIMUM_RENDER_OPACITY)
+            continue;
+        // Don't try rendering until texture exists
+        if (!item2D->qsgTexture)
+            continue;
+        QVector2D dimensions = QVector2D(item2D->qsgTexture->textureSize().width(),
+                                         item2D->qsgTexture->textureSize().height());
+        QSSGRenderTexture2D tex(renderer->context(), item2D->qsgTexture);
+
+        renderer->renderFlippedQuad(dimensions, item2D->MVP, tex, item2D->combinedOpacity);
+    }
+
     // transparent objects
     if (inEnableBlending || !layer.flags.testFlag(QSSGRenderLayer::Flag::LayerEnableDepthTest)) {
         theRenderContext->setBlendingEnabled(inEnableBlending);
@@ -880,20 +896,6 @@ void QSSGLayerRenderData::render(QSSGResourceFrameBuffer *theFB)
 
     renderer->beginLayerRender(*this);
     runRenderPass(renderRenderable, true, !layer.flags.testFlag(QSSGRenderLayer::Flag::LayerEnableDepthPrePass), false, true, 0, *camera, theFB);
-    for (auto theNodeEntry : getRenderableItem2Ds()) {
-        QSSGRenderItem2D *item2D = static_cast<QSSGRenderItem2D *>(theNodeEntry.node);
-        // Fast-path to avoid rendering totally transparent items
-        if (item2D->combinedOpacity < QSSG_RENDER_MINIMUM_RENDER_OPACITY)
-            continue;
-        // Don't try rendering until texture exists
-        if (!item2D->qsgTexture)
-            continue;
-        QVector2D dimensions = QVector2D(item2D->qsgTexture->textureSize().width(),
-                                         item2D->qsgTexture->textureSize().height());
-        QSSGRenderTexture2D tex(renderer->context(), item2D->qsgTexture);
-
-        renderer->renderFlippedQuad(dimensions, item2D->MVP, tex, item2D->combinedOpacity);
-    }
     renderer->endLayerRender();
 }
 
diff --git a/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderpreparationdata.cpp b/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderpreparationdata.cpp
index d87b599e4989f36d705c7e9438dc1607d532412e..446a543f45d26c0c1d60052edfb5631e87270e48 100644
--- a/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderpreparationdata.cpp
+++ b/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderpreparationdata.cpp
@@ -212,7 +212,44 @@ const QVector<QSSGRenderableObjectHandle> &QSSGLayerRenderPreparationData::getTr
 
 const QVector<QSSGRenderableNodeEntry> &QSSGLayerRenderPreparationData::getRenderableItem2Ds()
 {
-    return renderableItem2Ds;
+
+    if (!renderedItem2Ds.isEmpty() || camera == nullptr)
+        return renderedItem2Ds;
+
+    renderedItem2Ds = renderableItem2Ds;
+
+    const QVector3D cameraDirection(getCameraDirection());
+    const QVector3D cameraPosition = camera->getGlobalPos();
+
+    const auto isItemNodeDistanceGreatThan = [cameraDirection, cameraPosition]
+            (const QSSGRenderableNodeEntry &lhs, const QSSGRenderableNodeEntry &rhs) {
+        if (!lhs.node->parent || !rhs.node->parent)
+            return false;
+        const QVector3D lhsDifference = lhs.node->parent->position - cameraPosition;
+        const float lhsCameraDistanceSq = QVector3D::dotProduct(lhsDifference, cameraDirection);
+        const QVector3D rhsDifference = rhs.node->parent->position - cameraPosition;
+        const float rhsCameraDistanceSq = QVector3D::dotProduct(rhsDifference, cameraDirection);
+        return lhsCameraDistanceSq > rhsCameraDistanceSq;
+    };
+
+    const auto isItemZOrderLessThan = []
+            (const QSSGRenderableNodeEntry &lhs, const QSSGRenderableNodeEntry &rhs) {
+        if (lhs.node->parent && rhs.node->parent && lhs.node->parent == rhs.node->parent) {
+            // Same parent nodes, so sort with item z-ordering
+            QSSGRenderItem2D *lhsItem = static_cast<QSSGRenderItem2D *>(lhs.node);
+            QSSGRenderItem2D *rhsItem = static_cast<QSSGRenderItem2D *>(rhs.node);
+            return lhsItem->zOrder < rhsItem->zOrder;
+        }
+        return false;
+    };
+
+    // Render furthest to nearest items (parent nodes).
+    std::stable_sort(renderedItem2Ds.begin(), renderedItem2Ds.end(), isItemNodeDistanceGreatThan);
+    // Render items inside same node by item z-order.
+    // Note: stable_sort so item order in QML file is respected.
+    std::stable_sort(renderedItem2Ds.begin(), renderedItem2Ds.end(), isItemZOrderLessThan);
+
+    return renderedItem2Ds;
 }
 
 /**
@@ -810,7 +847,8 @@ bool QSSGLayerRenderPreparationData::prepareRenderablesForRender(const QMatrix4x
             theItem2D->calculateGlobalVariables();
             if (theItem2D->flags.testFlag(QSSGRenderModel::Flag::GloballyActive)) {
                 theItem2D->MVP = inViewProjection * theItem2D->globalTransform;
-                renderableItem2Ds.push_back(theNodeEntry);
+                // Pushing front to keep item order inside QML file
+                renderableItem2Ds.push_front(theNodeEntry);
             }
         } break;
         default:
@@ -1158,6 +1196,7 @@ void QSSGLayerRenderPreparationData::resetForFrame()
     lightDirections.clear();
     renderedOpaqueObjects.clear();
     renderedTransparentObjects.clear();
+    renderedItem2Ds.clear();
 }
 
 QT_END_NAMESPACE
diff --git a/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderpreparationdata_p.h b/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderpreparationdata_p.h
index 6aa05eb687fd668e429194be4430f81a42344736..57fd1fa4e75882d63cfda95e5f060f1c85104013 100644
--- a/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderpreparationdata_p.h
+++ b/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderpreparationdata_p.h
@@ -231,6 +231,7 @@ struct QSSGLayerRenderPreparationData
     // TNodeLightEntryPoolType m_RenderableNodeLightEntryPool;
     QVector<QSSGRenderableNodeEntry> renderableNodes;
     QVector<QSSGRenderableNodeEntry> renderableItem2Ds;
+    QVector<QSSGRenderableNodeEntry> renderedItem2Ds;
     TLightToNodeMap lightToNodeMap; // map of lights to nodes to cache if we have looked up a
     // given scoped light yet.
     // Built at the same time as the renderable nodes map.
diff --git a/tests/auto/quick3d_lancelot/data/quick/RenderingOrder.qml b/tests/auto/quick3d_lancelot/data/quick/RenderingOrder.qml
new file mode 100644
index 0000000000000000000000000000000000000000..f3e00b14bcf71ba579bd8a22055f30f8e631595e
--- /dev/null
+++ b/tests/auto/quick3d_lancelot/data/quick/RenderingOrder.qml
@@ -0,0 +1,344 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tests 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 QtQuick3D 1.15
+import QtQuick 2.15
+
+Rectangle {
+    width: 480
+    height: 480
+    color: Qt.rgba(1, 1, 0.5, 1)
+
+    View3D {
+        id: layer
+        anchors.fill: parent
+        environment: SceneEnvironment {
+            clearColor: Qt.rgba(0, 0, 0, 1)
+            aoDither: true
+            depthPrePassEnabled: true
+            depthTestEnabled: true
+        }
+
+        PerspectiveCamera {
+            position: Qt.vector3d(0, 0, 800)
+        }
+
+        DirectionalLight {
+        }
+
+        DirectionalLight {
+            eulerRotation.x: -30
+            eulerRotation.y: -70
+        }
+
+        // Model behind of everything else
+        Model {
+            position: Qt.vector3d(0, 100, -400)
+            eulerRotation: Qt.vector3d(45, 45, 45)
+            scale: Qt.vector3d(3.5, 3.5, 3.5)
+            source: "#Cube"
+            materials: DefaultMaterial {
+                diffuseColor: Qt.rgba(1, 0, 1, 1)
+            }
+        }
+
+        // Model in front of everything else
+        Model {
+            position: Qt.vector3d(0, -100, 450)
+            eulerRotation: Qt.vector3d(45, 45, 45)
+            scale: Qt.vector3d(1.0, 1.0, 1.0)
+            source: "#Cube"
+            opacity: 1.0
+            materials: DefaultMaterial {
+                diffuseColor: Qt.rgba(0, 1, 1, 1)
+            }
+        }
+
+        // Pile #1
+        Node {
+            x: -200
+            y: 250
+            Rectangle {
+                width: 200
+                height: 200
+                color: "red"
+                opacity: 0.8
+            }
+        }
+        Node {
+            x: -200
+            y: 250
+            z: 1
+            Rectangle {
+                width: 150
+                height: 150
+                color: "green"
+                opacity: 0.8
+            }
+        }
+        Node {
+            x: -200
+            y: 250
+            z: 2
+            Rectangle {
+                width: 100
+                height: 100
+                color: "blue"
+                opacity: 0.8
+            }
+        }
+
+        // Pile #2
+        Node {
+            x: 200
+            y: 250
+            Rectangle {
+                width: 200
+                height: 200
+                color: "red"
+                opacity: 0.8
+            }
+        }
+        Node {
+            x: 200
+            y: 250
+            z: 2
+            Rectangle {
+                width: 100
+                height: 100
+                color: "blue"
+                opacity: 0.8
+            }
+        }
+        Node {
+            x: 200
+            y: 250
+            z: 1
+            Rectangle {
+                width: 150
+                height: 150
+                color: "green"
+                opacity: 0.8
+            }
+        }
+
+        // Pile #3
+        Node {
+            x: -200
+            y: 0
+            z: -1
+            Rectangle {
+                width: 100
+                height: 100
+                color: "blue"
+                opacity: 0.8
+            }
+        }
+        Node {
+            x: -200
+            y: 0
+            z: -2
+            Rectangle {
+                width: 150
+                height: 150
+                color: "green"
+                opacity: 0.8
+            }
+        }
+        Node {
+            x: -200
+            y: 0
+            z: -3
+            Rectangle {
+                width: 200
+                height: 200
+                color: "red"
+                opacity: 0.8
+            }
+        }
+
+        // Pile #4
+        Node {
+            x: 200
+            y: 0
+            z: -1
+            Rectangle {
+                width: 100
+                height: 100
+                color: "blue"
+                opacity: 0.8
+            }
+        }
+        Node {
+            x: 200
+            y: 0
+            z: 20
+            NumberAnimation on z {
+                to: -2
+                duration: 200
+            }
+            Rectangle {
+                width: 150
+                height: 150
+                color: "green"
+                opacity: 0.8
+            }
+        }
+        Node {
+            x: 200
+            y: 0
+            z: 3
+            Component.onCompleted: {
+                z = -3;
+            }
+            Rectangle {
+                width: 200
+                height: 200
+                color: "red"
+                opacity: 0.8
+            }
+        }
+
+        // Pile #5 with 3D models
+        Model {
+            position: Qt.vector3d(-200, -250, -20)
+            eulerRotation: Qt.vector3d(45, 45, 45)
+            scale: Qt.vector3d(0.4, 0.4, 0.4)
+            opacity: 0.8
+            source: "#Cube"
+            Component.onCompleted: {
+                z = 20;
+            }
+            materials: DefaultMaterial {
+                diffuseColor: Qt.rgba(1, 1, 1, 1)
+            }
+        }
+        Model {
+            position: Qt.vector3d(-200, -250, -1)
+            scale: Qt.vector3d(2, 2, 0.01)
+            opacity: 0.8
+            source: "#Cube"
+            materials: DefaultMaterial {
+                diffuseColor: Qt.rgba(1, 0, 0, 1)
+            }
+        }
+        Node {
+            x: -200
+            y: -250
+            opacity: 0.8
+            Rectangle {
+                width: 150
+                height: 150
+                color: "green"
+                opacity: 0.8
+            }
+        }
+        Model {
+            position: Qt.vector3d(-200, -250, 1)
+            //eulerRotation: Qt.vector3d(-10,-10,-10)
+            scale: Qt.vector3d(1, 1, 0.01)
+            opacity: 0.8
+            source: "#Cube"
+            materials: DefaultMaterial {
+                diffuseColor: Qt.rgba(0, 0, 1, 1)
+            }
+        }
+
+        // Pile #6 with 3D models
+        Node {
+            x: 200
+            y: -250
+            z: 10
+            Rectangle {
+                width: 200
+                height: 200
+                color: "red"
+                opacity: 0.8
+            }
+        }
+        Node {
+            x: 200
+            y: -250
+            z: 10
+            Model {
+                scale: Qt.vector3d(1.5, 1.5, 0.01)
+                opacity: 0.8
+                source: "#Cube"
+                materials: DefaultMaterial {
+                    diffuseColor: Qt.rgba(0, 1, 0, 1)
+                }
+            }
+        }
+        Node {
+            x: 200
+            y: -250
+            z: 12
+            Rectangle {
+                width: 100
+                height: 100
+                color: "blue"
+                opacity: 0.8
+            }
+        }
+        Model {
+            position: Qt.vector3d(200, -250, -20)
+            eulerRotation: Qt.vector3d(45, 45, 45)
+            scale: Qt.vector3d(0.4, 0.4, 0.4)
+            source: "#Cube"
+            NumberAnimation on z {
+                to: 20
+                duration: 200
+            }
+            materials: DefaultMaterial {
+                diffuseColor: Qt.rgba(1, 1, 1, 1)
+            }
+        }
+    }
+}