Сцены Qt Quick 3D с 2D-содержимым
2D-элементы в 3D-мире
Qt Quick 3D обеспечивает эффективное создание и отрисовку сцен, объединяющих 3D и 2D-элементы.
Что мы подразумеваем под объединённой 3D-2D сценой?
По своей природе объект View3D, представляющий 3D-видовую область в 2D-сцене, может быть легко объединён с элементами Qt Quick, такими как Rectangle, Image, Text, расположенными вокруг, под или над элементом View3D, который сам по себе является элементом Qt Quick Item.
Рассмотрим следующий пример:
import QtQuick
import QtQuick3D
Rectangle {
gradient: Gradient {
GradientStop { position: 0; color: "steelblue" }
GradientStop { position: 1; color: "black" }
}
Text {
text: "Hello 2D World"
font.pointSize: 32
color: "red"
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
}
Item {
width: 400; height: 400
anchors.centerIn: parent
View3D {
anchors.fill: parent
environment: SceneEnvironment { backgroundMode: SceneEnvironment.Color; clearColor: "lightGray" }
PerspectiveCamera { z: 600 }
DirectionalLight { }
Model {
source: "#Cube"
materials: PrincipledMaterial { baseColor: "green"; metalness: 0.0; roughness: 0.0 }
eulerRotation: Qt.vector3d(30, 45, 0)
}
}
}
}Здесь 3D-сцена — область с серым фоном. Остальная часть окна состоит из 2D-элементов Qt Quick. Они могут перекрывать View3D, но не являются частью 3D-мира, не используют 3D-систему координат и не участвуют в преобразованиях 3D-сцены.
Что если мы хотим разместить 2D-элементы внутри 3D-мира таким образом, чтобы они действительно участвовали во всех 3D-преобразованиях? Например, можем ли мы разместить элементы Rectangle и Text внутри 3D-мира так, чтобы они следовали за вращением куба и всегда располагались над ним?
В следующих разделах мы рассмотрим, как этого можно добиться. Хотя в примере используются Rectangle и Text, можно использовать любой контент Qt Quick, включая Qt Quick Controls, Shape, ShaderEffect, ParticleSystem.
Примечание: Существуют и другие подходы к интеграции 2D-содержимого с 3D-объектами. Добавление 2D-элементов к 3D-узлам позволяет свободно комбинировать 2D и 3D-объекты в 3D-мире, но не позволяет отображать 2D-содержимое на поверхности 3D-объекта. Если цель заключается в текстурировании 3D-модели содержимым, сгенерированным Qt Quick, используйте свойство sourceItem Texture.
| Используемый как текстура контент Qt Quick | Элементы Qt Quick в 3D-сцене |
|---|---|
Добавление 2D-элементов к 3D-узлам
Ключевым фактором является способность Object3D принимать дочерние объекты Item и обрабатывать их особым образом. Object3D — базовый класс для типа Node. Это означает, что любые Node, а также типы, такие как Model, принимают дочерние элементы Item.
Начиная с Qt 6.0, добавление 2D-элемента к 3D-узлу больше не приводит к отображению 2D-содержимого в текстуре OpenGL, Vulkan image или аналогичном. Вместо этого, по умолчанию 2D-элементы отображаются вместе с остальной частью 3D-сцены в том же проходе отрисовки. К 2D-элементам применяются все 3D-преобразования. Преобразования наследуются от обертывающего Node.
import QtQuick
import QtQuick3D
Rectangle {
gradient: Gradient {
GradientStop { position: 0; color: "steelblue" }
GradientStop { position: 1; color: "black" }
}
Text {
text: "Hello 2D World"
font.pointSize: 32
color: "red"
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
}
Item {
width: 400; height: 400
anchors.centerIn: parent
View3D {
anchors.fill: parent
environment: SceneEnvironment { backgroundMode: SceneEnvironment.Color; clearColor: "lightGray" }
PerspectiveCamera { z: 600 }
DirectionalLight { }
Model {
Node {
y: 150
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
color: "white"
width: text3d.width
height: text3d.height
Text {
id: text3d
text: "Hello 3D World"
font.pointSize: 32
}
}
}
source: "#Cube"
materials: PrincipledMaterial { baseColor: "green"; metalness: 0.0; roughness: 0.0 }
eulerRotation: Qt.vector3d(30, 45, 0)
}
}
}
}По сравнению с первым фрагментом, у узла Model теперь есть дочерний узел с преобразованием, размещающим его несколько выше положения куба. 150 относительно центра куба в 3D-системе координат.
Model {
Node {
y: 150Затем есть элемент Rectangle. При добавлении его под Node границы 3D и 2D-мира пересекаются внутренне, но это остаётся прозрачным для разработчика приложения. Невидимый content item генерируется автоматически, позволяя Rectangle ссылаться на parent и выполнять привязку. 3D-преобразование из Node применяется ко всему 2D-поддереву. В примере это означает, что вращение будет соответствовать вращению куба.
Node {
y: 150
Rectangle {
anchors.horizontalCenter: parent.horizontalCenterСистемы координат в 2D и 3D
2D-элементы по-прежнему используют систему координат Qt Quick: ось Y направлена сверху вниз, а единицы соответствуют пикселям. 3D-узлы, с другой стороны, используют 3D-систему координат: ось Y направлена вверх, а единицы соответствуют сантиметрам, на которые влияет перспективная проекция камеры Camera.
По умолчанию верхний левый угол верхнего элемента размещается в начале координат Node. Это означает, что верхнему элементу 2D-поддерева часто потребуется указать привязку, например anchors.centerIn: parent, или, как в примере, привязку горизонтального центра к горизонтальному центру родителя, таким образом центрируя 2D-содержимое по горизонтали над 3D-узлом.
Дополнительные соображения
- Хотя 2D-элементы отрисовываются вместе с 3D-объектами, они не участвуют в освещении и не будут отбрасывать тени.
- Обрезка может работать не так, как ожидается, и следует избегать её. Если обрезка необходима для дизайна 2D-элементов, приложение должно явно вернуться к отрисовке в текстуру. Этого можно добиться, добавив
layer.enabled: trueк верхнемуItemпод 3D-узлом. - Начиная с Qt 6.0, ввод с клавиатуры, мыши и сенсорного экрана не передаётся 2D-элементам, поэтому они будут неинтерактивными.
- Хотя добавление 2D-дерева элементов в 3D-сцену довольно недорого, следует избегать чрезмерного количества (сотни или более) 2D-поддеревьев в 3D-сцене, так как в больших количествах это может привести к увеличению использования памяти и графических ресурсов. Обратите внимание, что это относится к количеству отдельных Item-поддеревьев под 3D-узлами, а не к общему числу 2D-элементов в этих поддеревьях. Например, в приведённом выше фрагменте QML содержится только одно 2D-поддерево.
См. также Qt Quick 3D - Пример с элементами Qt Quick.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.1/qtquick3d-2d.html