1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
6\title Instanced Rendering
7\page quick3d-instancing
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.)
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.
20In practice, instancing is done by defining a table that specifies how each instance is modified
21relative to the base model.
23\section1 Instancing API
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.
31The Instancing object specifies a table that defines how each copy is rendered. The available modifications are:
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
38Qt provides three QML types that inherit from Instancing:
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.
45The \l{Qt Quick 3D - Instanced Rendering Example}{instancing example} shows how to create a scene using the QML API.
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}.
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.
56The \l{Qt Quick 3D - Custom Instanced Rendering}{custom instancing example} shows how to combine
57custom materials and an instance table implemented in C++.
60\section1 Alpha-blending and instancing
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.
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.
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.
83The rendering order relative to the rest of the scene can be adjusted by setting the \l{Model::depthBias}{depth bias} of the model.
85\section1 Transforms and instancing
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:
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.
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:
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.
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.
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:
117 instancing: someInstanceTable
119 materials: DefaultMaterial { diffuseColor: "lightgray" }
124 instancing: cube.instancing
126 materials: DefaultMaterial { diffuseColor: "gray" }
128 NumberAnimation on eulerRotation.y {
132 loops: Animation.Infinite
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.
141\c instanceRoot can also be used when instancing a single model. For example, a cylinder rotating around an off-center point:
147 instanceRoot: parentNode
148 instancing: anotherInstanceTable
150 materials: DefaultMaterial { diffuseColor: "white" }
152 NumberAnimation on eulerRotation.y {
156 loops: Animation.Infinite
161\section1 Picking and instancing
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.