Sur cette page

Rendu volumétrique

Rendu d'objets volumétriques.

La section «Rendu volumétrique » explique comment utiliser QCustom3DVolume pour afficher des données volumétriques.

Rendu volumétrique d'un relief en 3D avec des couches d'eau et de terre

Exécution de l'exemple

Vous pouvez exécuter l'exemple à partir de :

Initialisation d’un élément de volume

Les éléments QCustom3DVolume sont des éléments personnalisés spéciaux (voir QCustom3DItem) qui peuvent être utilisés pour afficher des données volumétriques. Les éléments de volume ne sont pris en charge qu’avec la projection orthographique ; assurez-vous donc d’abord que le graphique utilise cette projection :

m_graph->setOrthoProjection(true);

Créez un élément volumétrique lié aux plages de données des axes :

m_volumeItem = new QCustom3DVolume;
// Adjust water level to zero with a minor tweak to y-coordinate position and scaling
m_volumeItem->setScaling(
            QVector3D(m_graph->axisX()->max() - m_graph->axisX()->min(),
                      (m_graph->axisY()->max() - m_graph->axisY()->min()) * 0.91f,
                      m_graph->axisZ()->max() - m_graph->axisZ()->min()));
m_volumeItem->setPosition(
            QVector3D((m_graph->axisX()->max() + m_graph->axisX()->min()) / 2.0f,
                      -0.045f * (m_graph->axisY()->max() - m_graph->axisY()->min()) +
                      (m_graph->axisY()->max() + m_graph->axisY()->min()) / 2.0f,
                      (m_graph->axisZ()->max() + m_graph->axisZ()->min()) / 2.0f));
m_volumeItem->setScalingAbsolute(false);

Indiquez que la mise à l’échelle du volume doit suivre les variations des plages de données en définissant la propriété ` QCustom3DItem::scalingAbsolute ` sur ` false`. Définissez ensuite le contenu interne du volume :

m_volumeItem->setTextureWidth(lowDetailSize);
m_volumeItem->setTextureHeight(lowDetailSize / 2);
m_volumeItem->setTextureDepth(lowDetailSize);
m_volumeItem->setTextureFormat(QImage::Format_Indexed8);
m_volumeItem->setTextureData(new QList<uchar>(*m_lowDetailData));

Utilisez une couleur indexée sur huit bits pour la texture, car elle est compacte et facilite l’ajustement des couleurs sans avoir à réinitialiser l’intégralité de la texture. Pour les données de texture, utilisez les données créées précédemment à partir de cartes d’altitude. En général, les données des éléments volumétriques sont pré-générées sous la forme d’une pile d’images ; vous pouvez donc ignorer les détails relatifs à la génération des données. Pour plus d’informations sur le processus de génération des données, consultez l’exemple de code.

Comme des couleurs indexées sur huit bits sont utilisées, une table de couleurs est nécessaire pour associer les index de couleur sur huit bits aux couleurs réelles. Dans un cas d’utilisation classique, vous récupérerez la table de couleurs à partir des images sources plutôt que d’en définir une manuellement :

m_volumeItem->setColorTable(m_colorTable1);

Pour pouvoir afficher des cadres de coupe autour du volume, initialisez leurs propriétés. Au départ, les cadres seront masqués :

m_volumeItem->setSliceFrameGaps(QVector3D(0.01f, 0.02f, 0.01f));
m_volumeItem->setSliceFrameThicknesses(QVector3D(0.0025f, 0.005f, 0.0025f));
m_volumeItem->setSliceFrameWidths(QVector3D(0.0025f, 0.005f, 0.0025f));
m_volumeItem->setDrawSliceFrames(false);

Enfin, ajoutez le volume en tant qu'élément personnalisé au graphique pour l'afficher :

m_graph->addCustomItem(m_volumeItem);

Découpage du volume

À moins que le volume ne soit en grande partie transparent, vous ne pouvez en voir que la surface, ce qui n’est souvent pas très utile. Une façon d’inspecter la structure interne du volume consiste à visualiser ses coupes. QCustom3DVolume propose deux méthodes pour afficher les coupes. La première consiste à afficher les coupes sélectionnées à la place du volume. Par exemple, pour spécifier une coupe perpendiculaire à l’axe X, utilisez la méthode suivante :

m_volumeItem->setSliceIndexX(m_sliceIndexX);

Pour afficher la coupe spécifiée ci-dessus, la propriété ` QCustom3DVolume::drawSlices ` doit également être définie :

m_volumeItem->setDrawSlices(true);

La deuxième méthode pour visualiser les tranches consiste à utiliser la méthode ` QCustom3DVolume::renderSlice()`, qui génère une image ` QImage ` à partir de la tranche spécifiée. Cette image peut ensuite être affichée dans un autre widget, tel qu’un ` QLabel` :

m_sliceLabelX->setPixmap(
            QPixmap::fromImage(m_volumeItem->renderSlice(Qt::XAxis, m_sliceIndexX)));

Réglage de la transparence du volume

Parfois, le simple fait de visualiser les coupes ne permet pas de bien comprendre la structure interne du volume. QCustom3DVolume fournit deux propriétés permettant de régler la transparence du volume :

m_volumeItem->setAlphaMultiplier(mult);
    ...
m_volumeItem->setPreserveOpacity(enabled);

La propriété « QCustom3DVolume::alphaMultiplier » est un multiplicateur général appliqué à la valeur alpha de chaque voxel du volume. Elle permet d’ajouter une transparence uniforme aux parties déjà quelque peu transparentes du volume afin de révéler les détails opaques internes. Ce multiplicateur n’affecte pas les couleurs entièrement opaques, sauf si la propriété « QCustom3DVolume::preserveOpacity » est définie sur « false ».

Une autre façon de régler la transparence du volume consiste à ajuster directement les valeurs alpha des voxels. Pour les textures indexées 8 bits, cela s'effectue simplement en modifiant puis en réinitialisant la table de couleurs :

int newAlpha = enabled ? terrainTransparency : 255;
for (int i = aboveWaterGroundColorsMin; i < underWaterGroundColorsMax; i++) {
    QRgb oldColor1 = m_colorTable1.at(i);
    QRgb oldColor2 = m_colorTable2.at(i);
    m_colorTable1[i] = qRgba(qRed(oldColor1), qGreen(oldColor1), qBlue(oldColor1), newAlpha);
    m_colorTable2[i] = qRgba(qRed(oldColor2), qGreen(oldColor2), qBlue(oldColor2), newAlpha);
}
if (m_usingPrimaryTable)
    m_volumeItem->setColorTable(m_colorTable1);
else
    m_volumeItem->setColorTable(m_colorTable2);

Shader haute définition vs shader basse définition

Par défaut, le rendu volumétrique utilise un shader haute définition. Il prend en compte chaque voxel du volume avec le poids approprié lors du ray tracing du contenu du volume, offrant ainsi une représentation précise des détails les plus fins du volume. Cependant, cette opération est très gourmande en ressources de calcul, ce qui nuit à la fréquence d’images. Si la vitesse de rendu est plus importante que la précision au pixel près du contenu du volume, utilisez le shader basse définition, bien plus rapide, en définissant la propriété « QCustom3DVolume::useHighDefShader » false. Le shader basse définition gagne en vitesse au détriment de la précision ; il ne garantit donc pas que chaque voxel du volume sera échantillonné. Cela peut entraîner un scintillement ou d’autres artefacts de rendu sur les détails les plus fins du volume.

m_volumeItem->setUseHighDefShader(enabled);

Exemple de contenu

Exemple de projet sur code.qt.io

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.