c++qtqt3dgeometry-instancing

Qt3D - Instance rendering of 2 squares. PrimitiveType? InstanceCount?


I'd like to display on the screen 2 squares using instance rendering.

The problem is :
When I draw 2 squares, they are connected. I can't draw multiple separate square.

I know it has to do with PrimitiveType : i'm using Qt3DRender::QGeometryRenderer::LineLoop or Qt3DRender::QGeometryRenderer::TriangleFan but is there a way to tell Qt to separate my data buffer in multiple instances ? so that the PrimitiveType apply on each instances and not all the vertices.

I got a function that create shapes :

Qt3DCore::QEntity* SceneBuilder::createShapeInstancing(const QList<QVector3D> & listVertices, int nbPointGeometry, const QColor color, Qt3DCore::QEntity * rootEntity) 
{
    // Material
    Qt3DExtras::QPhongMaterial *material = new Qt3DExtras::QPhongMaterial(rootEntity);
    material->setAmbient(color);

    // Custom entity
    Qt3DCore::QEntity *customMeshEntity = new Qt3DCore::QEntity(rootEntity);

    // Custom Mesh
    Qt3DRender::QGeometryRenderer *customMeshRenderer = new Qt3DRender::QGeometryRenderer(rootEntity);
    Qt3DRender::QGeometry *customGeometry = new Qt3DRender::QGeometry(customMeshRenderer);

    Qt3DRender::QBuffer *vertexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, customGeometry);

    int nbPointGeometry = nbPoint;

    QByteArray vertexBufferData;
    vertexBufferData.resize(listVertices.size() * nbPointGeometry * sizeof(QVector3D));
    QVector3D *posData = reinterpret_cast<QVector3D *>(vertexBufferData.data());

    QList<QVector3D>::const_iterator it;
    for (it = listVertices.begin(); it != listVertices.end(); it++)
    {
        *posData = *it;
        ++posData;
    }

    vertexDataBuffer->setData(vertexBufferData);

    //Attributes

    Qt3DRender::QAttribute *positionAttribute = new Qt3DRender::QAttribute();
    positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
    positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
    positionAttribute->setBuffer(vertexDataBuffer);
    positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
    positionAttribute->setVertexSize(3);
    positionAttribute->setByteOffset(0);
    positionAttribute->setByteStride((0 + 3) * sizeof(float));
    positionAttribute->setCount(listVertices.size());
    //positionAttribute->setDivisor(1);

    customGeometry->addAttribute(positionAttribute);

    customMeshRenderer->setGeometry(customGeometry);
    //customMeshRenderer->setInstanceCount(listVertices.size()/nbPoint);
    if (nbPointGeometry == 1)
        customMeshRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Points);
    else if (nbPointGeometry == 2)
        customMeshRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Lines);
    else if (nbPointGeometry == 3)
        customMeshRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles);
    else
        customMeshRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LineLoop);

    customMeshEntity->addComponent(customMeshRenderer);
    customMeshEntity->addComponent(material);

    return customMeshEntity;
}

When i call this function, i put my 2 squares inside the listVertices variables. So that all my squares are display in one draw call.

But the shapes are one way or another connected. Is there a way to remove that ? I'm not using InstanceCount or Divisor but i don't know how it works. I made some tests with it but nothing worked


Solution

  • Actually, I just found an example of instanced rendering here.

    They subclassed QSphereGeometry and performed the instanced rendering in a shader. You could create a RectangleGeometry which holds the vertices for one triangle and equip it with the same functionality as the InstancedGeometry in the example.

    Result:

    enter image description here