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) -> float { return m_gridSpacing * (i - m_gridSize / 2); };
int instanceNumber = 0;
for (int i = 0; i < m_gridSize; ++i) {
float xPos = idxToPos(i);
for (int j = 0; j < m_gridSize; ++j) {
float zPos = idxToPos(j);
int lowest = blocks.lowestVisible(i, j);
int highest = blocks.highestBlock(i, j);
for (int k = lowest; k <= 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<const char *>(&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.
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
VARYING vec4 vCustomData;
VARYING vec3 vGlobalPosition;
void MAIN()
{
vCustomData 


