GPU instancing #1545
-
I know there's one similar thread, but I'd like an answer for my exact case, if possible. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 6 replies
-
I have had a chance to write it up yet, but part of the 3D Tiles 1.0 work I recently checked into VSG/vsgXchange master included a new vsg::InstanceNode that is coupled to vsg::InstanceDraw and vsg::InstanceDrawIndexed. These new classes enable more flexible GPU instancing, adding higher level instancing support that provided by the lower level mesh drawing classes. The InstanceNode class provides the high level interface to the translation, rotations and scale arrays, while the InstanceDraw/InstanceDrawIndexed pass the instance arrays to Vulkan in the appropriate way. You can have multiple InstanceNode nodes sharing the same subgraph, which is used by 3D Tiles when rendering things like trees or lampposts, so that different tiles that require different number and values of instancing positions, but can share the same lower level scene graph. The new [vsgXchange::gltf](https://github.com/vsg-dev/vsgXchange/blob/master/include/vsgXchange/gltf.h] loader now supports a mode where it'll build the loaded model with InstanceDraw/InstanceDrawIndexed, enabling the calling code to add the required vsg::InstanceNode to decorate the loaded subgraphs. There are restrictions on what type of subgraphs are suitable for instancing in this way, and the new gltf loader aims to keep things compatible with InstanceNode when this mode is enabled. The implementation of the .i3dm format in the new vsgXchange 3DTiles code provides an example of the set up of the vsg::InstanceNode and how to tell the vsgXchange::gltf loader that it should create a subgraph suitable for use with InstanceNode. The relevant code can be found at in vsgXchange/src/3DTiles/i3dm.cpp. The code is: // if required decorate the model to provide multiple instances, or provide the global translation.
if (gpuInstancing)
{
// compute the centre of all positions
vsg::dvec3 instance_center;
if (featureTable->POSITION)
{
for (size_t i = 0; i*3 < featureTable->POSITION.values.size(); ++i)
{
const auto& values = featureTable->POSITION.values;
instance_center += vsg::dvec3(values[i*3 + 0], values[i*3 + 1], values[i*3 + 2]);
}
instance_center /= static_cast<double>(featureTable->POSITION.values.size()/3);
rtc_center += instance_center;
}
else if (featureTable->POSITION_QUANTIZED)
{
for (size_t i = 0; i*3 < featureTable->POSITION_QUANTIZED.values.size(); ++i)
{
const auto& values = featureTable->POSITION_QUANTIZED.values;
vsg::dvec3 quantizedPosition(static_cast<double>(values[i*3 + 0]), static_cast<double>(values[i*3 + 1]), static_cast<double>(values[i*3 + 2]));
instance_center += quantizeOffset + quantizedPosition * quantizeScale;
}
instance_center /= static_cast<double>(featureTable->POSITION_QUANTIZED.values.size()/3);
rtc_center += instance_center;
}
auto translations = vsg::vec3Array::create(featureTable->INSTANCES_LENGTH);
auto rotations = vsg::quatArray::create(featureTable->INSTANCES_LENGTH);
auto scales = vsg::vec3Array::create(featureTable->INSTANCES_LENGTH);
auto instanceNode = vsg::InstanceNode::create();
instanceNode->firstInstance = 0;
instanceNode->instanceCount = featureTable->INSTANCES_LENGTH;
instanceNode->setTranslations(translations);
instanceNode->setRotations(rotations);
instanceNode->setScales(scales);
instanceNode->child = model;
for(uint32_t i=0; i<featureTable->INSTANCES_LENGTH; ++i)
{
vsg::dvec3 translation, scale;
vsg::dquat rotation;
getTransformComponents(i, translation, rotation, scale);
translations->set(i, vsg::vec3(translation - instance_center));
rotations->set(i, vsg::quat(rotation));
scales->set(i, vsg::vec3(scale));
}
if (rtc_center != vsg::dvec3())
{
auto transform = vsg::MatrixTransform::create();
transform->addChild(instanceNode);
transform->matrix = vsg::translate(rtc_center);
model = transform;
}
else
{
model = instanceNode;
}
} The code is very much hot off the presses. I can't provide detailed support on this as I have heap of work to get on with. |
Beta Was this translation helpful? Give feedback.
I have had a chance to write it up yet, but part of the 3D Tiles 1.0 work I recently checked into VSG/vsgXchange master included a new vsg::InstanceNode that is coupled to vsg::InstanceDraw and vsg::InstanceDrawIndexed. These new classes enable more flexible GPU instancing, adding higher level instancing support that provided by the lower level mesh drawing classes.
The InstanceNode class provides the high level interface to the translation, rotations and scale arrays, while the InstanceDraw/InstanceDrawIndexed pass the instance arrays to Vulkan in the appropriate way. You can have multiple InstanceNode nodes sharing the same subgraph, which is used by 3D Tiles when rendering things like …