Volumetrisches Rendering

Rendering volumetrischer Objekte.

Volumetrisches Rendering zeigt, wie Sie QCustom3DVolume zur Darstellung volumetrischer Daten verwenden.

Ausführen des Beispiels

Zum Ausführen des Beispiels von Qt Creatorauszuführen, öffnen Sie den Modus Welcome und wählen Sie das Beispiel aus Examples. Weitere Informationen finden Sie unter Erstellen und Ausführen eines Beispiels.

Volumenelement initialisieren

Bei den Elementen QCustom3DVolume handelt es sich um spezielle benutzerdefinierte Elemente (siehe QCustom3DItem), die zur Anzeige volumetrischer Daten verwendet werden können. Die Volumenelemente werden nur bei orthografischer Projektion unterstützt, stellen Sie also zunächst sicher, dass das Diagramm sie verwendet:

m_graph->setOrthoProjection(true);

Erstellen Sie ein volumetrisches Element, das an die Datenbereiche der Achsen gebunden ist:

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);

Geben Sie an, dass die Skalierung des Volumens den Änderungen in den Datenbereichen folgen soll, indem Sie die Eigenschaft QCustom3DItem::scalingAbsolute auf false setzen. Als nächstes definieren Sie den internen Inhalt des Volumens:

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));

Verwenden Sie für die Textur eine indizierte 8-Bit-Farbe, da diese kompakt ist und die Farben leicht angepasst werden können, ohne dass die gesamte Textur zurückgesetzt werden muss. Verwenden Sie für die Texturdaten die zuvor auf der Grundlage von Höhenkarten erstellten Daten. Normalerweise werden die Daten für Volumenelemente in Form eines Stapels von Bildern vorgeneriert, so dass die Details der Datengenerierung übersprungen werden können. Weitere Informationen über den eigentlichen Datenerzeugungsprozess finden Sie im Beispielcode.

Da indizierte Acht-Bit-Farben verwendet werden, ist eine Farbtabelle erforderlich, um die Acht-Bit-Farbindizes den tatsächlichen Farben zuzuordnen. In einem typischen Anwendungsfall würden Sie die Farbtabelle aus den Quellbildern beziehen, anstatt eine manuell definierte zu verwenden:

m_volumeItem->setColorTable(m_colorTable1);

Um die Möglichkeit zu haben, Scheibenrahmen um das Volumen herum anzuzeigen, initialisieren Sie deren Eigenschaften. Zunächst werden die Rahmen ausgeblendet:

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);

Fügen Sie schließlich das Volumen als benutzerdefiniertes Element zum Diagramm hinzu, um es anzuzeigen:

m_graph->addCustomItem(m_volumeItem);

Schneiden in das Volumen

Wenn das Volumen nicht weitgehend transparent ist, können Sie nur die Oberfläche des Volumens sehen, was oft nicht sehr hilfreich ist. Eine Möglichkeit, die innere Struktur des Volumens zu untersuchen, besteht darin, die Slices des Volumens zu betrachten. QCustom3DVolume bietet zwei Möglichkeiten zur Anzeige der Slices. Die erste Möglichkeit besteht darin, die ausgewählten Slices anstelle des Volumes anzuzeigen. Um zum Beispiel ein Slices senkrecht zur X-Achse anzugeben, verwenden Sie die folgende Methode:

m_volumeItem->setSliceIndexX(m_sliceIndexX);

Um das oben angegebene Slices anzuzeigen, muss auch die Eigenschaft QCustom3DVolume::drawSlices eingestellt werden:

m_volumeItem->setDrawSlices(true);

Die zweite Möglichkeit, Schichten anzuzeigen, ist die Methode QCustom3DVolume::renderSlice(), die eine QImage aus der angegebenen Schicht erzeugt. Dieses Bild kann dann in einem anderen Widget angezeigt werden, z. B. in QLabel:

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

Einstellen der Volumentransparenz

Manchmal reicht es nicht aus, nur die Slices zu betrachten, um die interne Struktur des Volumens zu verstehen. QCustom3DVolume bietet zwei Eigenschaften, mit denen man die Transparenz des Volumens anpassen kann:

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

QCustom3DVolume::alphaMultiplier ist ein allgemeiner Multiplikator, der auf den Alpha-Wert jedes Voxels des Volumens angewendet wird. Er ermöglicht es, den bereits einigermaßen transparenten Teilen des Volumens eine einheitliche Transparenz hinzuzufügen, um interne undurchsichtige Details sichtbar zu machen. Dieser Multiplikator wirkt sich nicht auf Farben aus, die vollständig undurchsichtig sind, es sei denn, die Eigenschaft QCustom3DVolume::preserveOpacity ist auf false eingestellt.

Eine alternative Möglichkeit, die Transparenz des Volumens anzupassen, besteht darin, die Alphawerte der Voxel direkt zu verändern. Bei indizierten 8-Bit-Texturen wird dies einfach durch Ändern und Zurücksetzen der Farbtabelle erreicht:

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);

High Definition vs. Low Definition Shader

Standardmäßig wird für das volumetrische Rendering ein hochauflösender Shader verwendet. Er berücksichtigt jedes Voxel des Volumens mit der richtigen Gewichtung beim Raytracing des Volumeninhalts und liefert eine genaue Darstellung selbst der feinsten Details des Volumens. Dies ist jedoch sehr rechenintensiv, so dass die Bildrate darunter leidet. Wenn die Rendering-Geschwindigkeit wichtiger ist als die pixelgenaue Darstellung des Volumeninhalts, sollten Sie den viel schnelleren Low-Definition-Shader verwenden, indem Sie die Eigenschaft QCustom3DVolume::useHighDefShader false einstellen. Der Low-Definition-Shader erreicht die Geschwindigkeit, indem er Kompromisse bei der Genauigkeit eingeht, so dass er nicht garantiert, dass jedes Voxel des Volumens abgetastet wird. Dies kann zu Flackern oder anderen Rendering-Artefakten bei den feineren Details des Volumens führen.

m_volumeItem->setUseHighDefShader(enabled);

Beispiel Inhalt

Beispielprojekt @ code.qt.io

© 2025 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.