Instanced Rendering
实例渲染
Introduction
介绍
Qt Quick 3D supports instancing of Model objects. Instancing refers to a technique where one object is rendered multiple times with a single draw call. (For example the OpenGL function glDrawElementsInstanced
.)
Qt Quick 3D支持模型对象的实例化。实例化是指使用一个绘制调用多次渲染一个对象的技术。(例如,OpenGL函数glDrawElementsInstanced。)
Instancing allows duplicating a model with variations. In contrast to using a Repeater3D, the model and its graphics resources are only allocated once. The rendering of the duplicated instances is done at a low level by the GPU. Depending on the complexity of the model, this can give a performance improvement of several orders of magnitude.
实例化允许复制具有变量的模型。与使用Repeater3D不同,模型及其图形资源只分配一次。重复实例的渲染由GPU在低级别完成。根据模型的复杂性,这可以使性能提高几个数量级。
In practice, instancing is done by defining a table that specifies how each instance is modified relative to the base model.
实际上,实例化是通过定义一个表来完成的,该表指定每个实例相对于基础模型的修改方式。
Instancing API
实例API
The main principle of the instancing API is that it is explicit: It doesn't try to autodetect opportunities for instancing within the existing API. Instead, each model is marked individually by setting its instancing property to reference an Instancing object. The same Instancing object can be used on multiple models at the same time.
实例化API的主要原则是它是明确的:它不会尝试自动检测现有API中的实例化机会。相反,通过将其实例化属性设置为引用实例化对象,可以单独标记每个模型。同一实例对象可以同时用于多个模型。
The Instancing object specifies a table that defines how each copy is rendered. The available modifications are:
实例化对象指定一个表,该表定义如何渲染每个副本。可用的修改包括:
- transformation: position, rotation, and scale
- 变换:位置、旋转和缩放
- color: a color that is blended with the model’s material
- 颜色:与模型材质混合的颜色
- custom data: data that can be used by custom materials
- 自定义数据:可由自定义材质使用的数据
Qt provides three QML types that inherit from Instancing:
Qt提供了三种继承自实例的QML类型:
- InstanceList enumerates all instances and allows binding to the properties of each instance.
- InstanceList枚举所有实例,并允许绑定到每个实例的属性。
- RandomInstancing provides a way to quickly test and prototype by generating random instances within defined bounds.
- RandomInstancing通过在定义的范围内生成随机实例,提供了一种快速测试和原型化的方法。
- FileInstancing reads an instance table from an external file.
- FileInstance从外部文件读取实例表。
The instancing example shows how to create a scene using the QML API.
实例化示例显示了如何使用QML API创建场景。
Other kinds of instance tables can be defined in C++ by subclassing QQuick3DInstancing. For example, the particle system uses its own instancing table internally. It is available as ModelParticle3D.instanceTable.
通过子类化QQuick3DInstance,可以在C++中定义其他类型的实例表。例如,粒子系统在内部使用自己的实例化表。它作为ModelParticle3D.instanceTable提供。
By writing custom shader code, it is possible to use instancing to control additional properties, such as variables for physically based rendering, skeletal animation weights, distortion, or anything else that can be expressed with custom materials. The custom data in the instancing table consists of four floating point numbers.
通过编写自定义着色器代码,可以使用实例化来控制其他属性,例如用于基于物理的渲染的变量、骨骼动画权重、扭曲或可以用自定义材质表示的任何其他属性。实例化表中的自定义数据由四个浮点数组成。
The custom instancing example shows how to combine custom materials and an instance table implemented in C++.
自定义实例化示例显示了如何将自定义材质与C++实现的实例表相结合。
Alpha-blending and instancing
Alpha混合和实例化
Correct alpha blending requires that semi-transparent objects are rendered back-to-front. For this reason, QtQuick3D sorts opaque and semi-transparent objects separately, and renders them in the correct order. With instancing, however, the GPU will render the instances in the order specified by the instancing table, if depth-sorting is not turned on. For performance reasons, QtQuick3D does not sort the table by default as it can take long time with large number of instances. This means that if semi-transparent instances overlap with each other, or with other semi-transparent objects, the results may look wrong. In general, the error is less visible when the opacity is low.
正确的alpha混合需要将半透明对象渲染回前面。因此,QtQuick3D分别对不透明和半透明对象进行排序,并以正确的顺序渲染它们。但是,如果没有启用深度排序,使用实例化,GPU将按照实例化表指定的顺序呈现实例。出于性能原因,QtQuick3D默认情况下不会对表进行排序,因为大量实例可能需要很长时间。这意味着,如果半透明实例彼此重叠,或与其他半透明对象重叠,则结果可能看起来不正确。通常,当不透明度较低时,错误不太明显。
Fully opaque objects together with non-overlapping semi-transparent objects will always be rendered correctly, since Qt uses depth buffer testing to avoid drawing behind opaque objects. However, the lack of sorting has potential performance implications for opaque objects: They may not be rendered in the optimal order, meaning that the same pixel can be written multiple times, making more work for the fragment shader.
完全不透明对象和非重叠半透明对象将始终正确渲染,因为Qt使用深度缓冲区测试来避免在不透明对象后面绘制。但是,缺少排序对不透明对象有潜在的性能影响:它们可能不会以最佳顺序渲染,这意味着同一像素可以多次写入,从而为片段着色器带来更多工作。
The renderer does not inspect the contents of the instancing table, so it must be specified explicitly when an instance table contains semi-transparent alpha values: Set the hasTransparency property to to true
to make sure that the renderer enables alpha blending. This applies to all the instances: Even fully opaque instances will be rendered without depth testing, potentially causing visible errors.
渲染器不检查实例化表的内容,因此当实例表包含半透明alpha值时,必须明确指定它:将hasTransparency属性设置为true,以确保渲染器启用alpha混合。这适用于所有实例:即使完全不透明的实例也会在没有深度测试的情况下渲染,这可能会导致可见错误。
The rendering order relative to the rest of the scene can be adjusted by setting the depth bias of the model.
可以通过设置模型的深度偏移来调整相对于场景其余部分的渲染顺序。
Transforms and instancing
转换和实例化
Each instance has its own transform in the instance table. This is combined with the transforms on the instanced model. This is slightly complex, since there are several use cases:
每个实例在实例表中都有自己的转换。这与实例化模型上的变换相结合。这有点复杂,因为有几个用例:
- Doing a transform on the model that is applied to each individual instance. This allows cheap animations, for example by rotating all instances at once without having to change the instance table.
- 对应用于每个实例的模型进行转换。这允许廉价的动画,例如,通过一次旋转所有实例而无需更改实例表。
- Transforming the entire group of instances at once.
- 一次转换整个实例组。
- Instancing a model hierarchy.
- 实例化模型层次结构。
To support all these cases, The model’s transform is split into two parts: the local instance transform, and the global instance transform. Conceptually, instancing is performed like this:
为了支持所有这些情况,模型的转换分为两部分:本地实例转换和全局实例转换。从概念上讲,实例化的执行方式如下:
- First the model is transformed according to the local instance transform.
- 首先根据局部实例变换对模型进行变换。
- Then each instance is calculated by applying the instance table transform
- 然后通过应用实例表转换计算每个实例
- Finally, the whole group of instanced objects is transformed according to the global instance transform.
- 最后,根据全局实例变换变换整个实例化对象组。
By default, the local instance transform of a model consists of the model’s scale and rotation, while the rest goes into the global instance transform.
默认情况下,模型的局部实例变换由模型的缩放和旋转组成,而其余的则进入全局实例变换。
This can be controlled by setting the model’s instanceRoot property. This defines the origin of the instance’s coordinate system. The most common use is when instancing a hierarchy of models. For example, a sphere orbiting around a cube:
这可以通过设置模型的instanceRoot属性来控制。这将定义实例坐标系的原点。最常见的用法是实例化模型层次结构。例如,围绕立方体旋转的球体:
Model {
id: cube
instancing: someInstanceTable
source: "#Cube"
materials: DefaultMaterial { diffuseColor: "lightgray" }
Node {
Model {
source: "#Sphere"
instanceRoot: cube
instancing: cube.instancing
x: 150
materials: DefaultMaterial { diffuseColor: "gray" }
}
NumberAnimation on eulerRotation.y {
from: 0
to: 360
duration: 4000
loops: Animation.Infinite
}
}
}
The instanceRoot
is necessary to specify that the sphere instance should be positioned as if it were an element of the cube. Each model in a hierarchy still needs to specify the instancing
property: in normal cases they should all be set to the same Instancing
object.
必须使用instanceRoot来指定球体实例的位置,就像它是立方体的元素一样。层次中的每个模型仍然需要指定实例化属性:在正常情况下,它们都应该设置为同一个实例化对象。
instanceRoot
can also be used when instancing a single model. For example, a cylinder rotating around an off-center point:
在实例化单个模型时,也可以使用instanceRoot。例如,围绕偏心点旋转的圆柱体:
Node {
id: parentNode
Model {
source: "#Cylinder"
instanceRoot: parentNode
instancing: anotherInstanceTable
x: 25
materials: DefaultMaterial { diffuseColor: "white" }
}
NumberAnimation on eulerRotation.y {
from: 0
to: 360
duration: 1000
loops: Animation.Infinite
}
}
Picking and instancing
拾取和实例化
Picking is a mechanism that enables selecting a model from a user interface interaction. With instanced rendering, there are several representations of the same model, so the pick result will include an instance index. Instanced picking is enabled by setting the pickable property on the base model.
拾取是一种允许从用户界面交互中选择模型的机制。对于实例化渲染,同一模型有多个表示形式,因此拾取结果将包括一个实例索引。通过在基本模型上设置pickable属性,可以启用实例化拾取。
© 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.