There is a function that draws triangles through a wrapper over OpenGL.

I draw two triangles at the touch of a button (on_openMapPushButton_clicked () function).

Next, I draw a sphere that is above these triangles. And now, I see that the sphere above one triangle is drawn correctly, but the second triangle is drawn over the sphere, for some reason.

If I press the triangle drawing button again, the sphere will be drawn on top of two triangles.

When I press the button a third time, the situation returns to the original.

With the fourth push, the sphere is drawn again and so on.

If I use QPhongMaterial instead of QPhongAlphaMaterial, then the sphere is always drawn over the top, as it should be.

I do not understand what is the matter and how to make the sphere always drawn from above.

Fragment, drawing a transparent sphere:

selectModel_ = new Qt3DExtras::QSphereMesh(selectEntity_); selectModel_->setRadius(75); selectModel_->setSlices(150); selectMaterial_ = new Qt3DExtras::QPhongAlphaMaterial(selectEntity_); selectMaterial_->setAmbient(QColor(28, 61, 136)); selectMaterial_->setDiffuse(QColor(11, 56, 159)); selectMaterial_->setSpecular(QColor(10, 67, 199)); selectMaterial_->setShininess(0.8f); selectEntity_->addComponent(selectModel_); selectEntity_->addComponent(selectMaterial_); 

Triangle drawTriangles draw function:

 void drawTriangles(QPolygonF triangles, QColor color){ int numOfVertices = triangles.size(); // Создаем и заполняем вершинный буфер QByteArray bufferBytes; bufferBytes.resize(3 * numOfVertices * static_cast<int>(sizeof(float))); float *positions = reinterpret_cast<float*>(bufferBytes.data()); for(auto point : triangles){ *positions++ = static_cast<float>(point.x()); *positions++ = 0.0f; //We need to drow only on the surface *positions++ = static_cast<float>(point.y()); } geometry_ = new Qt3DRender::QGeometry(mapEntity_); auto *buf = new Qt3DRender::QBuffer(geometry_); buf->setData(bufferBytes); positionAttribute_ = new Qt3DRender::QAttribute(mapEntity_); positionAttribute_->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); positionAttribute_->setVertexBaseType(Qt3DRender::QAttribute::Float); //В буфере у нас будут флоаты positionAttribute_->setVertexSize(3); // Размер одной вершины positionAttribute_->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); // Тип атрибута positionAttribute_->setByteStride(3 * sizeof(float)); // Шаг между вершинами positionAttribute_->setBuffer(buf); // Сам буфер geometry_->addAttribute(positionAttribute_); // Добавляем атрибут в наш Qt3DRender::QGeometry // Создаем и заполняем индексный буфер QByteArray indexBytes; indexBytes.resize(numOfVertices * static_cast<int>(sizeof(unsigned int))); // start to end unsigned int *indices = reinterpret_cast<unsigned int*>(indexBytes.data()); for(unsigned int i = 0; i < static_cast<unsigned int>(numOfVertices); ++i) { *indices++ = i; } auto *indexBuffer = new Qt3DRender::QBuffer(geometry_); indexBuffer->setData(indexBytes); indexAttribute_ = new Qt3DRender::QAttribute(geometry_); // Создаем индексный атрибут indexAttribute_->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); // Тип данных в индексном буфере indexAttribute_->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); // Тип атрибута indexAttribute_->setBuffer(indexBuffer); // Сам индексный буфер indexAttribute_->setCount(static_cast<unsigned int>(numOfVertices)); // Количество вершин, как я понял geometry_->addAttribute(indexAttribute_); // Добавляем атрибут в наш Qt3DRender::QGeometry shape_ = new Qt3DRender::QGeometryRenderer(mapEntity_); shape_->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles); shape_->setGeometry(geometry_); // Устанавливаем нашу геометрию //Создаем материал material_ = new Qt3DExtras::QPhongMaterial(mapEntity_); material_->setAmbient(color); trianglesEntity_ = new Qt3DCore::QEntity(mapEntity_); trianglesEntity_->addComponent(shape_); // Добавляем наш рисунок trianglesEntity_->addComponent(material_); // Добавляем наш материал } 

The function of processing the on_openMapPushButton_clicked () button:

 void on_openMapPushButton_clicked() { clearMap(); //Реализация ниже QPolygonF triangle1; triangle1 << QPointF( 0 ,-1000) << QPointF(0 ,1000) << QPointF(1000, -1000); drawTriangles(triangle1, Qt::black); QPolygonF triangle2; triangle2 << QPointF(-1000,-1000) << QPointF(-100,1000) << QPointF(-100,-1000); drawTriangles(triangle2, Qt::red); } 

ClearMap () card cleaning function:

 void clearMap() { if(mapEntity_){ delete mapEntity_; mapEntity_ = nullptr; mapEntity_ = new Qt3DCore::QEntity(view3dRootEntity_); } } 

    1 answer 1

    My mistake was that I created and deleted the Entities in the wrong order.

    In pseudocode, the correct order is as follows:

     clearTriangles(); clearSphere(); drawTriangles(); drawSphere(); 

    The answers to the English version of my question have useful information on how you can still change the order of drawing using QSortPolicy or two FrameGraph: https://stackoverflow.com/questions/55001233/qt3d-draw-transparent-qspheremesh-over-triangles