Qt Quick 3D - Custom Instanced Rendering▲
This example shows how to create instance data programmatically in C++, and how to use custom materials with instanced rendering.
Custom instancing table▲
We define our table as a subclass of QQuick3DInstancing and add some properties so we can control it from QML:
class
CppInstanceTable : public
QQuick3DInstancing
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(int
gridSize READ gridSize WRITE setGridSize NOTIFY gridSizeChanged)
Q_PROPERTY(float
gridSpacing READ gridSpacing WRITE setGridSpacing NOTIFY gridSpacingChanged)
Q_PROPERTY(int
randomSeed READ randomSeed WRITE setRandomSeed NOTIFY randomSeedChanged)
The virtual function getInstanceBuffer is reimplemented to return the instancing data:
QByteArray CppInstanceTable::
getInstanceBuffer(int
*
instanceCount)
{
if
(m_dirty) {
BlockTable blocks(m_gridSize, m_randomSeed);
m_instanceData.resize(0
);
auto
idxToPos =
[this
](int
i) -&
gt; float
{
return
m_gridSpacing *
(i -
m_gridSize /
2
); }
;
int
instanceNumber =
0
;
for
(int
i =
0
; i &
lt; m_gridSize; ++
i) {
float
xPos =
idxToPos(i);
for
(int
j =
0
; j &
lt; m_gridSize; ++
j) {
float
zPos =
idxToPos(j);
int
lowest =
blocks.lowestVisible(i, j);
int
highest =
blocks.highestBlock(i, j);
for
(int
k =
lowest; k &
lt;=
highest; ++
k) {
float
yPos =
idxToPos(k);
QColor color =
blocks.getBlockColor(i, j, k);
float
waterAnimation =
blocks.isWaterSurface(i, j, k) ? 1.0
: 0.0
;
auto
entry =
calculateTableEntry({
xPos, yPos, zPos }
, {
1.0
, 1.0
, 1.0
}
, {}
, color, {
waterAnimation, 0
, 0
, 0
}
);
m_instanceData.append(reinterpret_cast
&
lt;const
char
*&
gt;(&
amp;entry), sizeof
(entry));
instanceNumber++
;
}
}
}
m_instanceCount =
instanceNumber;
m_dirty =
false
;
}
if
(instanceCount)
*
instanceCount =
m_instanceCount;
return
m_instanceData;
}
Custom material▲
We use a shaded custom material, meaning that Qt gives us the basic implementation, and we just specify additional logic.
The only customization we need for the vertex shader is for passing information to the fragment shader. By default, Qt only provides the instance data to the vertex shader, so we pass it on as vCustomData. We also calculate the global position of the vertex and make it available as vGlobalPosition.
VARYING vec4 vCustomData;
VARYING vec3 vGlobalPosition;
void
MAIN()
{
vCustomData =
INSTANCE_DATA;
// MODEL_MATRIX does not exist when instancing
vec4 pos =
INSTANCE_MODEL_MATRIX *
vec4(VERTEX,