Qt Quick 3D场景,包含2D内容

Qt Quick 3D Scenes with 2D Content

Qt Quick 3D场景,包含2D内容

2D Items in a 3D World

3D世界中的2D项目

Qt Quick 3D offers efficient creation and rendering of scenes that combine 3D and 2D elements.

Qt Quick 3D提供了结合3D和2D元素的场景的高效创建和渲染。

What do we mean by a combined 3D-2D scene?

我们所说的组合3D-2D场景是什么意思?

By nature, a View3D object, representing a 3D viewport in the 2D scene, can be easily combined with Qt Quick items, such as, Rectangle, Image, Text, around, below, or above the View3D item, which itself is a Qt Quick Item.

​本质上,表示2D场景中3D视口的View3D对象可以很容易地与Qt Quick项组合,例如矩形、图像、文本、View3D项周围、下方或上方,而View3D项本身就是Qt Quick项目。

Consider the following example:

考虑以下示例:

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)
            }
        }
    }
}

Here the 3D scene is the area with gray background. The rest of the window consists of 2D Qt Quick items. These can overlap with the View3D but are not part of the 3D world, are not using the 3D coordinate system, and do not take part in the 3D scene's transformations.

​这里的3D场景是具有灰色背景的区域。窗口的其余部分由2D Qt Quick项目组成。它们可以与View3D重叠,但不是3D世界的一部分,不使用3D坐标系,也不参与3D场景的变换。

What if we want to have 2D items within the 3D world, in a way that they truly participate in all 3D transforms? For example, can we have Rectangle and Text items placed within the 3D world, in a way that they follow the cube's rotation and are always placed above it?

​如果我们希望在3D世界中有2D项目,以使它们真正参与所有3D变换,该怎么办?例如,我们是否可以将矩形和文本项放置在三维世界中,使它们跟随立方体的旋转并始终放置在立方体上方?

In the following sections we will take a look at how this can be achieved. While the example uses Rectangle and Text, any Qt Quick content, including Qt Quick Controls, ShapeShaderEffectParticleSystem, can be used this way.

​在以下部分中,我们将了解如何实现这一点。虽然示例使用矩形和文本,但任何Qt Quick内容,包括Qt QuickControl、Shape、ShaderEffect和ParticleSystem,都可以这样使用。

Note: There are also other approaches available to integrate 2D content with the 3D objects. Adding 2D items to 3D nodes allows freely combining the 2D and 3D objects in the 3D world, but it does not allow rendering the 2D content on the surface of a 3D object. If the goal is to texture a 3D mesh with content generated by Qt Quick, use the sourceItem property of Texture instead.

​注意:还有其他方法可用于将2D内容与3D对象集成。将2D项添加到3D节点允许在3D世界中自由组合2D和3D对象,但不允许在3D对象的表面上渲染2D内容。如果目标是使用Qt Quick生成的内容对3D网格进行纹理处理,请改用纹理的sourceItem属性。

Qt Quick content used as a texture mapQt Quick items in the 3D scene

Adding 2D Items to 3D Nodes

向三维节点添加二维项

The key enabler is Object3D's ability to accept Item child objects, and treat them in a special way. Object3D is the base class for the Node type. This means that any Node, and also types like Model, accept Item children.

​关键的使能因素是Object3D能够接受项子对象,并以特殊方式处理它们。Object3D是节点类型的基类。这意味着,任何节点以及模型等类型都接受项子项。

Starting with Qt 6.0, adding a 2D item to a 3D node no longer triggers rendering the 2D content into a OpenGL texture, Vulkan image, or similar. Rather, the default mode is to render the 2D items in-line with the rest of the 3D scene, in the same render pass. The 2D items have all 3D transformations applied. The transformations are inherited from the wrapping Node.

从Qt 6.0开始,向3D节点添加2D项不再触发将2D内容渲染为OpenGL纹理、Vulkan图像或类似内容。相反,默认模式是在同一渲染过程中与3D场景的其余部分对齐渲染2D项目。2D项目应用了所有3D变换。转换是从包装节点继承的。

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)
            }
        }
    }
}
​

Compared to the first snippet, the Model node now has a child node, with a transform that places it somewhat above the cube's position. 150 is relative to the cube's center, in the 3D coordinate space.

​与第一个片段相比,模型节点现在有一个子节点,通过变换将其放置在立方体位置的上方。150相对于立方体的中心。

Model {
    Node {
        y: 150

Then there is the Rectangle item. When adding it under a Node, the boundaries of the 3D and 2D world are crossed internally, but this remains transparent to the application designer. An invisible content item is generated automatically, allowing the Rectangle to refer to parent and perform anchoring. The 3D transform from the Node is applied to the entire 2D subtree. In the example this means that the rotation will match the cube's rotation.

​然后是矩形项。当将其添加到节点下时,3D和2D世界的边界在内部交叉,但这对于应用程序设计者来说仍然是透明的。自动生成不可见的内容项,允许矩形引用父项并执行锚定。来自节点的3D变换应用于整个2D子树。在示例中,这意味着旋转将匹配立方体的旋转。

Node {
    y: 150
    Rectangle {
        anchors.horizontalCenter: parent.horizontalCenter

Coordinate Spaces in 2D and 3D

二维和三维空间坐标

The 2D items continue to use Qt Quick's coordinate system: Y axis runs from top to bottom, and the units correspond to pixels. 3D nodes on the other hand use the 3D coordinate system: the Y axis points up, and the units correspond to centimeters, affected by the Camera's perspective projection.

​2D项目继续使用Qt Quick的坐标系:Y轴从上到下,单位对应于像素。另一方面,3D节点使用3D坐标系:Y轴指向上,单位对应于厘米,受摄影机透视投影的影响。

The top item's top-left corner is placed at the Node's origin by default. This means that the top-level item in a 2D subtree will often want to specify an anchor, for example anchors.centerIn: parent, or, like in the example, anchoring the horizontal center to the parent' horizontal center, thus centering the 2D content horizontally over the 3D node.

默认情况下,顶部项的左上角位于节点的原点。这意味着2D子树中的顶级项通常需要指定锚,例如anchors.centerIn: parent,或如本例中所示,将水平中心锚定到父节点的水平中心,从而使2D内容水平居中于3D节点之上。

Further Considerations

进一步考虑

  • While the 2D items are rended in-line with 3D objects, they do not participate in lighting, and will not be casting shadows.
  • 虽然2D项目与3D对象对齐渲染,但它们不参与照明,也不会投射阴影。
  • Clipping may not perform as expected and should be avoided. If clipping is essential to the design of 2D items, the application should make an explicit fall back to rendering to a texture. This can be achieved by adding layer.enabled: true to the top-level Item under the 3D node.
  • 剪裁可能无法按预期执行,应避免。如果剪裁对于2D项目的设计至关重要,则应用程序应明确退回到渲染纹理。这可以通过添加layer.enabled: true来实现3D节点下的顶级项。
  • As of Qt 6.0, keyboard, mouse, and touch input is not passed to the 2D items, so they will be non-interactive.
  • 从Qt 6.0开始,键盘、鼠标和触摸输入不会传递到2D项目,因此它们将是非交互式的。
  • While adding a 2D item tree into the 3D scene is fairly cheap, excess amounts (hundreds or more) of 2D subtrees within the 3D scene should be avoided, because in large amounts this may lead to increased memory and graphics resource usage. Note that this refers to the number of separate Item subtrees under 3D nodes, not the total number of 2D items in those subtrees. For example, the QML snippet above contains only one 2D subtree.
  • ​虽然将2D项目树添加到3D场景中相当便宜,但应避免3D场景中的2D子树数量过多(数百或更多),因为在大量情况下,这可能导致内存和图形资源使用增加。请注意,这指的是3D节点下的单独项目子树的数量,而不是这些子树中的2D项目总数。例如,上面的QML片段只包含一个2D子树。

See also Qt Quick 3D - Quick Items Example.

​另请参见Qt Quick 3D-快速项目示例。

© 2022 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值