Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qtquick3d-instancing.qdoc
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3
4/*!
5
6\title Instanced Rendering
7\page quick3d-instancing
8
9\section1 Introduction
10
11Qt Quick 3D supports instancing of \l [QtQuick3D | QML] {Model} objects. Instancing refers to a
12technique where one object is rendered multiple times with a single draw call. (For example the
13OpenGL function \c glDrawElementsInstanced.)
14
15Instancing allows duplicating a model with variations. In contrast to using a \l{Repeater3D}, the
16model and its graphics resources are only allocated once. The rendering of the duplicated instances
17is done at a low level by the GPU. Depending on the complexity of the model, this can give a
18performance improvement of several orders of magnitude.
19
20In practice, instancing is done by defining a table that specifies how each instance is modified
21relative to the base model.
22
23\section1 Instancing API
24
25The main principle of the instancing API is that it is explicit: It doesn't try to autodetect
26opportunities for instancing within the existing API. Instead, each model is marked individually by
27setting its \l{Model::instancing}{instancing} property to reference an \l [QtQuick3D | QML]
28{QtQuick3D::Instancing}{Instancing} object. The same Instancing object can be used on multiple
29models at the same time.
30
31The Instancing object specifies a table that defines how each copy is rendered. The available modifications are:
32\list
33\li \e{transformation}: position, rotation, and scale
34\li \e{color}: a color that is blended with the model’s material
35\li \e{custom data}: data that can be used by custom materials
36\endlist
37
38Qt provides three QML types that inherit from Instancing:
39\list
40\li \l {InstanceList} enumerates all instances and allows binding to the properties of each instance.
41\li \l {RandomInstancing} provides a way to quickly test and prototype by generating random instances within defined bounds.
42\li \l {FileInstancing} reads an instance table from an external file.
43\endlist
44
45The \l{Qt Quick 3D - Instanced Rendering Example}{instancing example} shows how to create a scene using the QML API.
46
47Other kinds of instance tables can be defined in C++ by subclassing \l{QQuick3DInstancing}. For example, the
48\l {ParticleSystem3D}{particle system} uses its own instancing table internally. It is available as
49\l{ModelParticle3D::instanceTable}{ModelParticle3D.instanceTable}.
50
51By writing custom shader code, it is possible to use instancing to control additional properties,
52such as variables for physically based rendering, skeletal animation weights, distortion, or anything
53else that can be expressed with custom materials. The custom data in the instancing table consists
54of four floating point numbers.
55
56The \l{Qt Quick 3D - Custom Instanced Rendering}{custom instancing example} shows how to combine
57custom materials and an instance table implemented in C++.
58
59
60\section1 Alpha-blending and instancing
61
62Correct alpha blending requires that semi-transparent objects are rendered back-to-front. For this
63reason, QtQuick3D sorts opaque and semi-transparent objects separately, and renders them in the
64correct order. With instancing, however, the GPU will render the instances in the order specified by
65the instancing table, if \l {Instancing::depthSortingEnabled}{depth-sorting} is not turned on.
66For performance reasons, QtQuick3D does not sort the table by default as it can take long time with
67large number of instances. This means that if semi-transparent instances overlap with each other,
68or with other semi-transparent objects, the results may look wrong. In general, the error is less
69visible when the opacity is low.
70
71Fully opaque objects together with non-overlapping semi-transparent objects will always be rendered
72correctly, since Qt uses depth buffer testing to avoid drawing behind opaque objects. However, the
73lack of sorting has potential performance implications for opaque objects: They may not be rendered
74in the optimal order, meaning that the same pixel can be written multiple times, making more work
75for the fragment shader.
76
77The renderer does not inspect the contents of the instancing table, so it must be specified
78explicitly when an instance table contains semi-transparent alpha values: Set the
79\l{Instancing::hasTransparency}{hasTransparency} property to to \c true to make sure that the renderer enables alpha
80blending. This applies to all the instances: Even fully opaque instances will be rendered
81without depth testing, potentially causing visible errors.
82
83The rendering order relative to the rest of the scene can be adjusted by setting the \l{Model::depthBias}{depth bias} of the model.
84
85\section1 Transforms and instancing
86
87Each instance has its own transform in the instance table. This is combined with the transforms on
88the instanced model. This is slightly complex, since there are several use cases:
89
90\list
91\li Doing a transform on the model that is applied to each individual instance. This allows cheap
92animations, for example by rotating all instances at once without having to change the instance table.
93\li Transforming the entire group of instances at once.
94\li Instancing a model hierarchy.
95\endlist
96
97To support all these cases, The model’s transform is split into two parts: the
98\e{local instance transform}, and the \e{global instance transform}.
99Conceptually, instancing is performed like this:
100
101\list
102\li First the model is transformed according to the local instance transform.
103\li Then each instance is calculated by applying the instance table transform
104\li Finally, the whole group of instanced objects is transformed according to the global instance transform.
105\endlist
106
107By default, the local instance transform of a model consists of the model’s scale and rotation,
108while the rest goes into the global instance transform.
109
110This can be controlled by setting the model’s \l{Model::instanceRoot}{instanceRoot} property. This
111defines the origin of the instance’s coordinate system. The most common use is when instancing a
112hierarchy of models. For example, a sphere orbiting around a cube:
113
114\qml
115Model {
116 id: cube
117 instancing: someInstanceTable
118 source: "#Cube"
119 materials: DefaultMaterial { diffuseColor: "lightgray" }
120 Node {
121 Model {
122 source: "#Sphere"
123 instanceRoot: cube
124 instancing: cube.instancing
125 x: 150
126 materials: DefaultMaterial { diffuseColor: "gray" }
127 }
128 NumberAnimation on eulerRotation.y {
129 from: 0
130 to: 360
131 duration: 4000
132 loops: Animation.Infinite
133 }
134 }
135}
136\endqml
137
138The \c instanceRoot is necessary to specify that the sphere instance should be positioned as if it were an element of the cube.
139Each model in a hierarchy still needs to specify the \c instancing property: in normal cases they should all be set to the same \c Instancing object.
140
141\c instanceRoot can also be used when instancing a single model. For example, a cylinder rotating around an off-center point:
142\qml
143 Node {
144 id: parentNode
145 Model {
146 source: "#Cylinder"
147 instanceRoot: parentNode
148 instancing: anotherInstanceTable
149 x: 25
150 materials: DefaultMaterial { diffuseColor: "white" }
151 }
152 NumberAnimation on eulerRotation.y {
153 from: 0
154 to: 360
155 duration: 1000
156 loops: Animation.Infinite
157 }
158}
159\endqml
160
161\section1 Picking and instancing
162
163\l{View3D::pick}{Picking} is a mechanism that enables selecting a model from a user interface
164interaction. With instanced rendering, there are several representations of the same model, so the
165pick result will include an \l {pickResult::instanceIndex}{instance index}. Instanced picking is
166enabled by setting the \l {Model::pickable}{pickable} property on the base model.
167
168*/